你踩过几种C++内存泄露的坑?
C语言与CPP编程
共 2548字,需浏览 6分钟
·
2021-10-22 10:20
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_ptr
pObj = 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_ptr
pArrayObjs = 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_ptr
m_pPreNode; std::shared_ptr
m_pNextNode; int m_iVal;
};
void MemoryLeakLoopReference()
{
std::shared_ptr
pFirstNode = std::make_shared (100); std::shared_ptr
pSecondNode = std::make_shared (200); pFirstNode->m_pNextNode = pSecondNode;
pSecondNode->m_pPreNode = pFirstNode;
//Iterate nodes
auto 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_ptr
m_pPreNode; std::weak_ptr
m_pNextNode; int m_iVal;
};
void MemoryLeakLoopRefference()
{
std::shared_ptr
pFirstNode = std::make_shared (100); std::shared_ptr
pSecondNode = std::make_shared (200); pFirstNode->m_pNextNode = pSecondNode;
pSecondNode->m_pPreNode = pFirstNode;
//Iterate nodes
auto 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;
}
}
评论