在c++开发过程中,内存泄漏是令程序员最苦恼的事情,有时为了找到一个内存泄漏的地方,要调试很长时间。重载new操作符,往往是很多大型项目常用的防内存泄漏的手段。本人闲来无事,写了个new操作符重载的函数,大家互相学习,有不足之处还望大家给予指正。
上代码,就不做过多的解释啦。
1 #ifndef _BASE_H_ 2 #define _BASE_H_ 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <map> 7 using namespace std; 8 9 typedef struct { 10 unsigned long address; 11 unsigned long size; 12 char file[64]; 13 unsigned long line; 14 } ALLOC_INFO; 15 16 typedef map<unsigned long, ALLOC_INFO*> AllocMap; 17 18 AllocMap* allocMap; 19 20 #ifdef _DEBUG 21 #define DEBUG_NEW new(__FILE__, __LINE__) 22 23 void AddTrack(unsigned long addr, unsigned long asize, const char *fname, unsigned long lnum) 24 { 25 ALLOC_INFO *info = new ALLOC_INFO(); 26 info->address = addr; 27 strncpy(info->file, fname, 63); 28 info->line = lnum; 29 info->size = asize; 30 if (!allocMap) 31 { 32 allocMap = new AllocMap; 33 } 34 allocMap->insert(make_pair(addr,info)); 35 } 36 37 void RemoveTrack(unsigned long addr) 38 { 39 if(!allocMap || 0 == allocMap->size()) 40 { 41 return; 42 } 43 AllocMap::iterator iter = allocMap->find(addr); 44 if (iter != allocMap->end()) 45 { 46 ALLOC_INFO* info = iter->second; 47 delete info; 48 allocMap->erase(iter); 49 } 50 } 51 52 inline void * operator new(unsigned int size, const char *file, int line) 53 { 54 void *ptr = (void *)malloc(size); 55 AddTrack((unsigned long)ptr, size, file, line); 56 return(ptr); 57 } 58 59 inline void operator delete(void *p) 60 { 61 RemoveTrack((unsigned long)p); 62 free(p); 63 } 64 65 inline void * operator new[](unsigned int size, const char *file, int line) 66 { 67 void *ptr = (void *)malloc(size); 68 AddTrack((unsigned long)ptr, size, file, line); 69 return(ptr); 70 } 71 72 inline void operator delete[](void *p) 73 { 74 RemoveTrack((unsigned long)p); 75 free(p); 76 } 77 #else // _DEBUG 78 #define DEBUG_NEW new 79 #endif // _DEBUG 80 81 // 用于检测内存并做最后的内存清理 82 void DumpUnfreed() 83 { 84 AllocMap::iterator iter; 85 ALLOC_INFO* info; 86 unsigned long totalSize = 0; 87 if(!allocMap || 0 == allocMap->size()) 88 { 89 return; 90 } 91 92 for(iter = allocMap->begin(); iter != allocMap->end(); iter++) 93 { 94 printf("%-50s: LINE %d, ADDRESS %d %d unfreed\n", iter->second->file, iter->second->line 95 , iter->second->address, iter->second->size); 96 totalSize += iter->second->size; 97 info = iter->second; 98 delete info; 99 } 100 printf("----------------------------------------------------------- \n"); 101 printf("Total Unfreed: %d bytes \n", totalSize); 102 delete allocMap; 103 }; 104 105 #endif // _BASE_H_
1 #include "base.h" 2 #define new DEBUG_NEW 3 4 int main() 5 { 6 char* pszCeshi = new char[5]; 7 DumpUnfreed(); 8 return 0; 9 }
最终运行结果如下:
c:\c++\test\test\main.cpp : LINE 6, ADDRESS 6637816 5 unfreed
-----------------------------------------------------------
Total Unfreed: 5 bytes
有些编译器会报:warning C4291: “void *operator new(unsigned int,const char *,int)”: 未找到匹配的删除运算符;如果初始化引发异常,则不会释放内存
要防止这种报错,可以再定义两个delete方法。如下:
inline void operator delete(void *p , const char *file, int line) { RemoveTrack((unsigned long)p); free(p); } inline void operator delete[](void *p, const char *file, int line) { RemoveTrack((unsigned long)p); free(p); }