这里是一个简单的内存泄漏自动检查机制。只适用于单线程情况下。工作原理就是将已经分配的内存用一个双向链表串联起来,释放内存时从链表里删除。在程序退出时,将链表中未释放的内存打印出来。同时在内存块中保存文件名和行号,用于定位内存分配地址。
// placement_new.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <cassert>
#define ASSERT assert
char buff[1024];
using namespace std;
struct MEMORY_TAG
{
int nSize;
const char* szFile;
int nLine;
MEMORY_TAG* pPrev;
MEMORY_TAG* pNext;
};
MEMORY_TAG g_header = {0, 0, 0, 0, 0};
// 打印出所有未释放的内存
void DumpUnAllocatedMem()
{
for(MEMORY_TAG* pEntry = g_header.pNext; pEntry; pEntry = pEntry->pNext)
{
printf("%s(%d) : leak %d bytes\n", pEntry->szFile ? pEntry->szFile : "", pEntry->nLine, pEntry->nSize);
}
}
// 统计已经分配的内存块数和字节数
int CountOfAllocatedMem(void* pnSize= NULL)
{
int nCount = 0;
size_t allocated = 0;
for(MEMORY_TAG* pEntry = g_header.pNext; pEntry; pEntry = pEntry->pNext)
{
allocated += pEntry->nSize;
nCount++;
}
printf("%d count, %d total\n", nCount, allocated);
return nCount;
}
// 实现一个全局operator new可以有文件名和行号作为参数
void* operator new(size_t size, const char* pszFile, int line)
{
size_t nRealSize = size + sizeof(MEMORY_TAG);
MEMORY_TAG* pTag = (MEMORY_TAG*)malloc(nRealSize);
pTag->nSize = nRealSize;
pTag->szFile = pszFile;
pTag->nLine = line;
// 插入队列头部
if (g_header.pNext)
{
g_header.pNext->pPrev = pTag;
}
pTag->pNext = g_header.pNext;
g_header.pNext = pTag;
pTag->pPrev = &g_header;
return pTag + 1;
}
void* operator new(size_t size)
{
return (operator new(size, __FILE__, __LINE__));
}
void operator delete(void* p, const char*, int line)
{
delete p;
}
void operator delete(void* p)
{
MEMORY_TAG* pTag = (MEMORY_TAG*)(((char*)p)-sizeof(MEMORY_TAG));
// 从队列中删除
pTag->pPrev->pNext = pTag->pNext;
if (pTag->pNext)
{
pTag->pNext->pPrev = pTag->pPrev;
}
free(pTag);
}
class Object
{
public:
Object()
{
cout << "Object's contructor." << endl;
}
~Object()
{
cout << "Object's destructor." << endl;
}
char data[1024];
};
#define NEW new(__FILE__, __LINE__)
int _tmain(int argc, _TCHAR* argv[])
{
ASSERT(CountOfAllocatedMem() == 0);
Object* pObj = new(buff) Object;
pObj->~Object();
pObj = NEW(Object);
ASSERT(CountOfAllocatedMem() == 1);
delete pObj;
ASSERT(CountOfAllocatedMem() == 0);
pObj = NEW Object;
ASSERT(CountOfAllocatedMem() == 1);
delete pObj;
ASSERT(CountOfAllocatedMem() == 0);
pObj = NEW Object;
char* p = new char[968];
ASSERT(CountOfAllocatedMem() == 2);
DumpUnAllocatedMem();
return 0;
}