这里是一个简单的内存泄漏自动检查机制。只适用于单线程情况下。工作原理就是将已经分配的内存用一个双向链表串联起来,释放内存时从链表里删除。在程序退出时,将链表中未释放的内存打印出来。同时在内存块中保存文件名和行号,用于定位内存分配地址。
001 // placement_new.cpp : Defines the entry point for the console application.
002 //
003
004 #include "stdafx.h"
005 #include <ioStream>
006 #include <cassert>
007
008 #define ASSERT assert
009 char buff[1024];
010
011 using namespace std;
012
013 struct MEMORY_TAG
014 {
015 int nSize;
016 const char* szFile;
017 int nLine;
018 MEMORY_TAG* pPrev;
019 MEMORY_TAG* pNext;
020 };
021
022 MEMORY_TAG g_header = {0, 0, 0, 0, 0};
023 // 打印出所有未释放的内存
024 void DumpUnAllocatedMem()
025 {
026 for(MEMORY_TAG* pEntry = g_header.pNext; pEntry; pEntry = pEntry->pNext)
027 {
028 printf("%s(%d) : leak %d bytes ", pEntry->szFile ? pEntry->szFile : "", pEntry->nLine, pEntry->nSize);
029 }
030 }
031 // 统计已经分配的内存块数和字节数
032 int CountOfAllocatedMem(void* pnSize= NULL)
033 {
034 int nCount = 0;
035 size_t allocated = 0;
036 for(MEMORY_TAG* pEntry = g_header.pNext; pEntry; pEntry = pEntry->pNext)
037 {
038 allocated += pEntry->nSize;
039 nCount++;
040 }
041 printf("%d count, %d total ", nCount, allocated);
042 return nCount;
043 }
044
045 // 实现一个全局operator new可以有文件名和行号作为参数
046 void* operator new(size_t size, const char* pszFile, int line)
047 {
048 size_t nRealSize = size + sizeof(MEMORY_TAG);
049 MEMORY_TAG* pTag = (MEMORY_TAG*)malloc(nRealSize);
050
051 pTag->nSize = nRealSize;
052 pTag->szFile = pszFile;
053 pTag->nLine = line;
054 // 插入队列头部
055 if (g_header.pNext)
056 {
057 g_header.pNext->pPrev = pTag;
058 }
059 pTag->pNext = g_header.pNext;
060 g_header.pNext = pTag;
061 pTag->pPrev = &g_header;
062
063 return pTag + 1;
064 }
065
066 void* operator new(size_t size)
067 {
068 return (operator new(size, __FILE__, __LINE__));
069 }
070
071
072 void operator delete(void* p, const char*, int line)
073 {
074 delete p;
075 }
076
077 void operator delete(void* p)
078 {
079 MEMORY_TAG* pTag = (MEMORY_TAG*)(((char*)p)-sizeof(MEMORY_TAG));
080 // 从队列中删除
081 pTag->pPrev->pNext = pTag->pNext;
082 if (pTag->pNext)
083 {
084 pTag->pNext->pPrev = pTag->pPrev;
085 }
086 free(pTag);
087 }
088
089 class Object
090 {
#p#副标题#e#
091 public:
092 Object()
093 {
094 cout << "Object's contructor." << endl;
095 }
096
097 ~Object()
098 {
099 cout << "Object's destructor." << endl;
100 }
101
102 char data[1024];
103 };
104
105 #define NEW new(__FILE__, __LINE__)
106
107 int _tmain(int argc, _TCHAR* argv[])
108 {
109 ASSERT(CountOfAllocatedMem() == 0);
110 Object* pObj = new(buff) Object;
111
112 pObj->~Object();
113
114 pObj = NEW(Object);
115 ASSERT(CountOfAllocatedMem() == 1);
116
117 delete pObj;
118 ASSERT(CountOfAllocatedMem() == 0);
119
120 pObj = NEW Object;
121 ASSERT(CountOfAllocatedMem() == 1);
122 delete pObj;
123 ASSERT(CountOfAllocatedMem() == 0);
124
125 pObj = NEW Object;
126
127 char* p = new char[968];
128 ASSERT(CountOfAllocatedMem() == 2);
129
130 DumpUnAllocatedMem();
131 return 0;
132 }
#p#副标题#e#