Here is a simple automatic memory leak check mechanism. Only applicable to single-threaded scenarios. The working principle is to concatenate allocated memory with a two-way linked list and delete the memory from the linked list when it is released. When the program exits, the unreleased memory in the linked list is printed. Saves the file name and row number in the memory block to locate the memory allocation address.
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
1024 char buff [];
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 };
023 // print out all unreleased memory
024 void DumpUnAllocatedMem ()
025 {
026 for (MEMORY_TAG * pEntry = g_header.pNext; pEntry = pEntry-> pNext)
027 {
028 printf ("% s (% d): leak % d bytes", pEntry-> szFile? PEntry-> szFile: "", pEntry-> nLine, pEntry-> nSize );
029}
030}
031 // count the allocated memory blocks and Cell Lines
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-> pNext)
037 {
038 allocated + = pEntry-> nSize;
039 nCount ++;
040}
041 printf ("% d count, % d total", nCount, allocated );
042 return nCount;
043}
044
045 // implement a global operator new with the file name and row number as parameters
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 // Insert the queue Header
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 // Delete from queue
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}