博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c++重载new操作符,防止内存泄露

Posted on 2011-11-13 16:01  开源云  阅读(2441)  评论(1编辑  收藏  举报

在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);
}