你踩過幾種C++內(nèi)存泄露的坑?

1. 函數(shù)內(nèi)或者類成員內(nèi)存未釋放
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 []
調(diào)用了 operator new從堆上申請所需的空間調(diào)用 XXX_Class的構(gòu)造函數(shù)
調(diào)用了 XXX_Class的析構(gòu)函數(shù)通過 operator delete?釋放了內(nèi)存
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創(chuàng)建一個對象,并且返回一個PROGRAMER_HANDLE(即void *),對應(yīng)用程序屏蔽其實(shí)際類型DoSomething?提供了一個功能去做一些事情,輸入的參數(shù),即為通過InitObj申請的對象應(yīng)用程序使用完畢后,一般需要釋放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. 對象循環(huán)引用
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;}}
評論
圖片
表情




