這裡是一個簡單的內存洩漏自動檢查機制。只適用於單線程情況下。工作原理就是將已經分配的內存用一個雙向鏈表串聯起來,釋放內存時從鏈表裡刪除。在程序退出時,將鏈表中未釋放的內存打印出來。同時在內存塊中保存文件名和行號,用於定位內存分配地址。
001 // placement_new.cpp : Defines the entry point for the console application.
002 //
003
004 #include "stdafx.h"
005 #include
006 #include
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 C++ountOfAllocatedMem(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 {
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 }