当前位置:文档之家› 几个内存泄漏的例子

几个内存泄漏的例子

几个内存泄漏的例子✧new和delete要成对使用✧new和delete要匹配经常看到一些C++方面的书籍中这样提及到内存泄漏问题,这样的说法的意思是比较明白,但对于初学C++程序员还是很难掌握,所以下面举几个反面的例子,希望对大家有帮助。

例一:错误处理流程中的return导致的内存泄漏bool MyFun(){CMyObject* pObj = NULL;pObj = new CMyObject();…if (…)return false;…if(…)return false;…if (pObj != NULL)delete pObj;return true;}注意:红色字体部分的return之前没有释放pObj,导致内存泄漏。

例二:exception改变了程序的正常流程,导致内存泄漏情况1:HRESULT MyFun(){HRESULT hr = S_OK;try{CMyObject* pObj = NULL;pObj = new CMyObject();…if (…){hr = E_FAIL;throw hr;}…if(…){hr = E_FAIL;throw hr;}…if (pObj != NULL)delete pObj;}catch (HRESULT& eHr){}return hr;}情况2:void OtherFun() // 可能是自己写的其他函数;// 也可能是其他人写的函数;// 也可能是系统的API;{…if(…)throw exception;…}bool MyFun(){CMyObject* pObj = NULL;pObj = new CMyObject();…OtherFun();…if (pObj != NULL)delete pObj;return true;}注意:上面的两种情况中的throw行为将导致程序的正常流程,一旦有throw的动作发生,pObj对象将不会被正确释放(delete)。

例三:忘记释放系统API创建的资源,导致内存泄露bool CMyClass::MyFun(){HANDLE hHandle = CreateEvent(NULL,FALSE,TRUE,NULL);…if (…)return false;…return true;}注意:系统API CreateEvent创建的HANDLE对象,需要自己释放,否则会导致内存泄漏。

还有其他一些系统的API也是如此,如:CreateFile、CreateFileMapping 等等,所以我们在使用不熟悉的系统API时,一定要仔细阅读MSDN。

例四:PostMessage可能导致的内存泄漏// 自定义的消息结构体typedef struct tagMSG{int i;float f;}MSG;// 发送消息的函数void MyFun(){MSG* pMsg = new MSG;…PostMessage(m_hWnd, WM_MYEVENT, (WPARAM)pMsg, 0);}// 接收消息的函数afx_msg void OnMessage(WPARAM wParam, LPARAM lParam){MSG* pMsg = (MSG*)wParam;m_i = pMsg->i;m_f = pMsg->f;}注意:OnMessage函数中忘记释放pMsg,导致内存泄漏。

例五:函数返回new的对象而导致的内存泄漏char* MyFun(){char* p = new char[10];…return p;}注意:调用MyFun程序的人可能不会注意到MyFun函数内部new出的对象,往往会忽略对象p的释放。

例六:不好的类结构也会导致内存泄漏// MyClass.h文件class MyClass{public:MyClass();virtual ~MyClass();BOOL Init();BOOL UnInit();private:char* m_pStr;}// MyClass.cpp文件MyClass::MyClass(): m_pStr(NULL){}MyClass::~MyClass(){}BOOL MyClass::Init(){m_pStr = new char[100];…if (…){delete m_pStr;m_pStr = NULL;return FALSE;}return TRUE;}BOOL MyClass::UnInit(){if (m_pStr != NULL){delete m_pStr;m_pStr = NULL;}return TRUE;}注意:这个类在Init()函数中new出类资源,需要调用相应的UnInit()函数来释放资源,但有些时候这个类需要给其他人使用,别人在使用时可能会忘记调用UnInit()函数来释放资源,这样就造成了内存泄漏,为了防止这个问题发生,最好在MyClass::~MyClass()函数中也进行资源释放。

如下写法:MyClass::~MyClass(){UnInit();}例七:容易忽视的深层次结构对象的内存泄漏typedef struct MyStruct{int i;BSTR bstr;}void MyFun(OLECHAR * sz){MyStruct* pStru = new MyStruct;…pStru->bstr = SysAllocString(sz);…delete pStru;}注意:pStru是个深层次结构的对象,在这个对象内部还有指针数据类型bstr,在释放pStr时,如果忘记了释放其内部的指针对象bstr,也会导致内存泄漏。

当然这个例子比较简单,在我们实际编程时,深层次结构的对象要比这个复杂的多,所以处理这些对象时需要格外小心。

例八:虚基类的析构函数可能导致的问题///////////////////////////// Base.hclass Base{public:Base();~Base();virtual void TestFun();}// Base.cppBase::Base(){}Base::~Base(){if (m_pStr != NULL){delete m_pStr;}}void Base::TestFun(){}////////////////////////////// // MyClass.hclass MyClass : public Base {public:MyClass();~MyClass();virtual void TestFun(); protected:char* m_pStr;}// MyClass.cppMyClass::MyClass(): m_pStr(NULL){}MyClass::~MyClass(){if (m_pStr != NULL)delete m_pStr;}void MyClass::TestFun(){m_pStr = new char[100];}/////////////////////////////// Test.cppint _tmain(int argc, _TCHAR* argv[]){Base* pClass = new CMyClass();pClass->TestFun();delete pClass;return 0;}注意:由于Base类的析构函数不是virtual类型,在_tmain程序的用法中,将会导致CMyClass的析构不会被调用,引起内存泄漏。

总结:1、C++编程中,内存泄漏是个比较烦人的问题,创建(new)对象的“入口”一般只有一处,但需要释放(delete)对象的“出口”却很多,而且由于创建(new)出来的对象的生存周期不固定,所以要完全避免内存泄漏是比较困难,需要我们在编程时格外小心;2、养成良好的代码书写习惯,尽量在编写代码时解决内存泄漏问题;3、一旦程序中发生内存泄漏时,可以使用一些内存泄漏检查工具(如:Bound Check等)来查找,这些工具可以帮助我们找出部分的内存泄漏的代码;4、有些内存泄漏的问题还需要我们手工查找,检查代码的逻辑也是查找内存泄漏的一种有效手段。

相关主题