你踩过几种C++内存泄露的坑?

1. 函数内或者类成员内存未释放
void MemoryLeakFunction(){XXX_Class * pObj = new XXX_Class();pObj->DoSomething();return;}
class MemoryLeakClass{public:MemoryLeakClass(){m_pObj = new XXX_ResourceClass;}void DoSomething(){m_pObj->DoSomething();}~MemoryLeakClass(){;}private:XXX_ResourceClass* m_pObj;};
void MemoryLeakFunction(){std::unique_ptrpObj = make_unique (); pObj->DoSomething();return;}
2. delete []
调用了 operator new从堆上申请所需的空间调用 XXX_Class的构造函数
调用了 XXX_Class的析构函数通过 operator delete释放了内存
class MemoryLeakClass{public:MemoryLeakClass(){m_pStr = new char[100];}void DoSomething(){strcpy_s(m_pStr, 100, "Hello Memory Leak!");std::cout << m_pStr << std::endl;}~MemoryLeakClass(){delete m_pStr;}private:char *m_pStr;};void MemoryLeakFunction(){const int iSize = 5;MemoryLeakClass* pArrayObjs = new MemoryLeakClass [iSize];for (int i = 0; i < iSize; i++){(pArrayObjs+i)->DoSomething();}delete pArrayObjs;}
void MemoryLeakFunction(){const int iSize = 5;std::unique_ptrpArrayObjs = std::make_unique (iSize); for (int i = 0; i < iSize; i++){(pArrayObjs.get()+i)->DoSomething();}}
3. delete (void*)
InitObj创建一个对象,并且返回一个PROGRAMER_HANDLE(即void *),对应用程序屏蔽其实际类型DoSomething提供了一个功能去做一些事情,输入的参数,即为通过InitObj申请的对象应用程序使用完毕后,一般需要释放SDK申请的对象,提供了 FreeObj
typedef void * PROGRAMER_HANDLE;PROGRAMER_HANDLE InitObj(){MemoryLeakClass* pObj = new MemoryLeakClass();return (PROGRAMER_HANDLE)pObj;}void DoSomething(PROGRAMER_HANDLE pHandle){((MemoryLeakClass*)pHandle)->DoSomething();}void FreeObj(void *pObj){delete pObj;}
void FreeObj(void *pObj){delete ((MemoryLeakClass*)pObj);}
4. Virtual destructor
class Father{public:virtual void DoSomething(){std::cout << "Father DoSomething()" << std::endl;}};class Child : public Father{public:Child(){std::cout << "Child()" << std::endl;m_pStr = new char[100];}~Child(){std::cout << "~Child()" << std::endl;delete[] m_pStr;}void DoSomething(){std::cout << "Child DoSomething()" << std::endl;}protected:char* m_pStr;};void MemoryLeakVirualDestructor(){Father * pObj = new Child;pObj->DoSomething();delete pObj;}
class Father{public:virtual void DoSomething(){std::cout << "Father DoSomething()" << std::endl;}virtual ~Father() { ; }};class Child : public Father{public:Child(){std::cout << "Child()" << std::endl;m_pStr = new char[100];}virtual ~Child(){std::cout << "~Child()" << std::endl;delete[] m_pStr;}void DoSomething(){std::cout << "Child DoSomething()" << std::endl;}protected:char* m_pStr;};
5. 对象循环引用
struct Node{Node(int iVal){m_iVal = iVal;}~Node(){std::cout << "~Node(): " << "Node Value: " << m_iVal << std::endl;}void PrintNode(){std::cout << "Node Value: " << m_iVal << std::endl;}std::shared_ptrm_pPreNode; std::shared_ptrm_pNextNode; int m_iVal;};void MemoryLeakLoopReference(){std::shared_ptrpFirstNode = std::make_shared (100); std::shared_ptrpSecondNode = std::make_shared (200); pFirstNode->m_pNextNode = pSecondNode;pSecondNode->m_pPreNode = pFirstNode;//Iterate nodesauto pNode = pFirstNode;while (pNode){pNode->PrintNode();pNode = pNode->m_pNextNode;}}
struct Node{Node(int iVal){m_iVal = iVal;}~Node(){std::cout << "~Node(): " << "Node Value: " << m_iVal << std::endl;}void PrintNode(){std::cout << "Node Value: " << m_iVal << std::endl;}std::shared_ptrm_pPreNode; std::weak_ptrm_pNextNode; int m_iVal;};void MemoryLeakLoopRefference(){std::shared_ptrpFirstNode = std::make_shared (100); std::shared_ptrpSecondNode = std::make_shared (200); pFirstNode->m_pNextNode = pSecondNode;pSecondNode->m_pPreNode = pFirstNode;//Iterate nodesauto pNode = pFirstNode;while (pNode){pNode->PrintNode();pNode = pNode->m_pNextNode.lock();}}
6. 资源泄露
void MemroyLeakFileHandle(){HANDLE hFile = CreateFile(LR"(C:\test\doc.txt)",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (INVALID_HANDLE_VALUE == hFile){std::cerr << "Open File error!" << std::endl;return;}const int BUFFER_SIZE = 100;char pDataBuffer[BUFFER_SIZE];DWORD dwBufferSize;if (ReadFile(hFile,pDataBuffer,BUFFER_SIZE,&dwBufferSize,NULL)){std::cout << dwBufferSize << std::endl;}}
void MemroyLeakFileHandle(){HANDLE hFile = CreateFile(LR"(C:\test\doc.txt)",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);std::unique_ptr< HANDLE, std::function<void(HANDLE*)>> phFile(&hFile,[](HANDLE* pHandle) {if (nullptr != pHandle){std::cout << "Close Handle" << std::endl;CloseHandle(*pHandle);}});if (INVALID_HANDLE_VALUE == *phFile){std::cerr << "Open File error!" << std::endl;return;}const int BUFFER_SIZE = 100;char pDataBuffer[BUFFER_SIZE];DWORD dwBufferSize;if (ReadFile(*phFile,pDataBuffer,BUFFER_SIZE,&dwBufferSize,NULL)){std::cout << dwBufferSize << std::endl;}}
评论




