防止handle忘记关闭,或者被关闭多次,以及防止内存忘记释放,或者释放多次
来源:互联网 发布:中国cpu 知乎 编辑:程序博客网 时间:2024/04/29 03:59
// HandleTest2.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <Windows.h>#include <iostream>using namespace std;#include "SmartHandle.h"#include "SmartPtr.h"#include "TestClass.h"// Testing the CAutoHandle template class.// Additional feature: misusing of handle wrapper as pointer// is not compiled.int _tmain(int argc, _TCHAR* argv[]){ // test smart handles CAutoLibrary hLibrary; hLibrary = LoadLibrary(_T("psapi.dll")); CAutoGeneralHandle hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); SetEvent(hEvent); // hLibrary->unused = 0; // not compiled, exactly as needed // test smart pointers CAutoPointer<CTestClass>::AutoPtr pTest = new CTestClass(); pTest->DoSomething(); CAutoArrayPointer<CTestClass>::AutoPtr pArrayTest = new CTestClass[2];return 0;}
// SmartPtr.h#pragma once// Additional release algorithms which allow to use// CSmartHandle as smart pointer// *******************************************************************************// Release algorithm for plain pointer.// Using this release algorithm CSmartHandle works// like simple smart pointer.template <typename T, class PointedBy>struct CClosePointer{ void Close(T handle) { delete (PointedBy*)handle; }protected: ~CClosePointer() { }};// I want to make typedef for using CSmartHandle with CClosePointer policy.// However, I cannot do this because user needs to provide class name parameter.// I can use define:// #define CAUTOPOINTER(ClassName) CSmartHandle<ClassName*, CClosePointer, ClassName>// Client code is:// CAUTOPOINTER(CTestClass) pTestClass = new CTestClass();//// but more elegant solution is constructing new type:template <class T>struct CAutoPointer{ typedef CSmartHandle<T*, CClosePointer, T> AutoPtr;};// Client code is:// CAutoPointer<CTestClass>::AutoPtr pTestClass = new CTestClass();//// the struct CAutoPointer itself has no members apart from the type definition // and isn't instantiated, it's only used to provide the type member // which returns the type I need.// *******************************************************************************// Release algorithm for plain array.template <typename T, class PointedBy>struct CCloseArrayPointer{ void Close(T handle) { delete[] (PointedBy*)handle; }protected: ~CCloseArrayPointer() { }};//#define CAUTOARRAYPOINTER(ClassName) CSmartHandle<ClassName*, CCloseArrayPointer, ClassName>template <class T>struct CAutoArrayPointer{ typedef CSmartHandle<T*, CCloseArrayPointer, T> AutoPtr;};
在写代码时候,经常会将一个Handle关闭多次,或者不关闭,包括内存释放也同样.可能大部分人觉得对一个handle关闭多次不会有问题, 但在管家项目中,就出现这样的Crash.
为了防止这样的问题: 就必须使用智能指针.
// SmartHandle.h#pragma once// Class CSmartHandle works like Jeffrey Richter's EnsureCleanup class// (Windows HANDLE wrapper which releases handle in destructor).// The change: instead of release function pointer it uses template // class (using the same technique as described in // Modern C++ Design by Andrei Alexandrescu.//// Classes CCloseHandle, CCloseRegKey... are releasing policies.// These classes are templates. Class CSmartHandle has second parameter// ReleaseAlgorithm which is release policy template.// This means, CSmartHandle template declaration contains// nesting template. This code is compiled in Visual Stidio .NET 2003// but not compiled in previous versions.//// Protected destructors prevent client code to release CSmartHandle// using release pointer code (see Modern C++ Design, // 1.7 Destructors of Policy Classes).//// Additional PointedBy algorithm prevents misusing of the smart handle// instance as smart pointer (using -> with handle is not compiled).// Release algorithms (release policies)template <typename T, class PointedBy>struct CCloseHandle{ void Close(T handle) { cout << "Handle is released" << endl; // for testing CloseHandle(handle); }protected: ~CCloseHandle() { }};template <typename T, class PointedBy>struct CCloseRegKey{ void Close(T handle) { RegCloseKey(handle); }protected: ~CCloseRegKey() { }};template <typename T, class PointedBy>struct CCloseLibrary{ void Close(T handle) { cout << "Library is released" << endl; // for testing FreeLibrary(handle); }protected: ~CCloseLibrary() { }};template <typename T, class PointedBy>struct CCloseViewOfFile{ void Close(T handle) { UnmapViewOfFile(handle); }protected: ~CCloseViewOfFile() { }};// Empty class used as default CAutoHandle template parameter.class CEmptyClass{};// Class CSmartHandle which implements release policy.// Second template parameter is ReleaseAlgorithm which is template itself.template <typename HandleType, template <class, class> class ReleaseAlgorithm, class PointedBy = CEmptyClass, // used for smart pointers HandleType NULL_VALUE = NULL>class CSmartHandle : public ReleaseAlgorithm<HandleType, PointedBy>{public: CSmartHandle() { m_Handle = NULL_VALUE; } CSmartHandle(HandleType h) { m_Handle = h; } HandleType operator=(HandleType h) { CleanUp(); m_Handle = h; return(*this); } operator HandleType() { return m_Handle; } PointedBy* operator->() // for using as smart pointer { // NOTE: adding this operator allows to use CAutoHandle object as pointer. // However, if PointedBy is CHandlePlaceHolder (used for handles), // this is not compiled because CHandlePlaceHolder has no functions. // This is exactly what I need. return m_Handle; } BOOL IsValid() { return m_Handle != NULL_VALUE; } ~CSmartHandle() { CleanUp(); }protected: void CleanUp() { if ( m_Handle != NULL_VALUE ) { Close(m_Handle); m_Handle = NULL_VALUE; } } HandleType m_Handle;};// Client code (definitions of standard Windows handles).typedef CSmartHandle<HANDLE, CCloseHandle> CAutoGeneralHandle;typedef CSmartHandle<HKEY, CCloseRegKey> CAutoRegKey;typedef CSmartHandle<PVOID, CCloseViewOfFile> CAutoViewOfFile;typedef CSmartHandle<HMODULE, CCloseLibrary> CAutoLibrary;typedef CSmartHandle<HANDLE, CCloseHandle, CEmptyClass, INVALID_HANDLE_VALUE> CAutoFile;
- 防止handle忘记关闭,或者被关闭多次,以及防止内存忘记释放,或者释放多次
- ODBC连接数据库 防止忘记释放内存
- ODBC连接数据库 防止忘记释放内存之使用模版类
- 防止用户多次点击按钮,导致发送多次请求或者其他问题。
- qt 对话框关闭以及自动释放内存
- 关闭窗体释放内存
- 防止忘记
- 防止页面被多次提交
- 防止页面被多次提交
- 防止页面多次被提交
- 防止页面被多次提交
- 防止页面被多次提交
- 防止控件被多次点击
- winform 关闭窗体 释放内存
- 防止程序多次打开
- 防止程序多次打开
- 防止按钮多次提交
- 防止程序多次运行。
- spring学习笔记(IOC-控制反转)
- C有序链表的终极插入函数
- xcode 4.2 调试5.1真机
- hibernate级联删除
- 学习链接
- 防止handle忘记关闭,或者被关闭多次,以及防止内存忘记释放,或者释放多次
- sharepoint2010管理permission levels
- java中byte,String,InputStream之间的转换
- xfire+Sping+安全认证
- 看门狗watchdog
- USB接口的EMI和ESD设计方案
- grub
- 用 Java 实现断点续传 (HTTP)
- 图标资源