C++ 重载new和delete操作符

原因:

C++标准库提供的new和delete操作符,是一个通用实现,未针对具体对象做具体分析
存在分配器速度慢、小型对象空间浪费严重等问题,不适用于对效率和内存有限制的应用场景
 

好处:

灵活的内存分配控制
提高和改善内存使用效率
检测代码内存错误
获取内存使用统计数据
 

C++标准规定:

分配函数应该是一个类成员函数或全局函数
若分配函数出于非全局命名空间或在全局命名空间声明为静态,则格式错误
要求的内存大小为0 byte时也应返回有效的内存地址
 

备注:

operator new具有一定特殊性,对于自定义类型不重载也可使用,其他操作符则不然
参数个数可以任意,只需保证第一个参数为size_t类型,饭后void *类型即可,其他操作符重载时参数需保持严格一致
因此new操作符更像一个函数重载,而非操作符重载
重载operator new时要兼容默认的operator new错误处理方式
 

实现:

简单实现

 1 void* operator new(size_t size)
 2 {
 3     if (size < 0)
 4         return 0;
 5     if (size == 0)
 6         size = 1;
 7         
 8     void *res = malloc(size);    
 9     return res;
10 }
11 
12 void operator delete(void* p)
13 {
14     if (p != 0)
15         free(p);
16 }
17 
18 void* operator new[](size_t size)
19 {
20     return operator new(size);
21 }
22 
23 void operator delete[](void* src)
24 {
25     operator delete(src);
26 }
View Code

跨平台实现及其内存检测:(来源:http://www.linuxidc.com/Linux/2011-07/39154p4.htm

  1 #ifndef _DEBUG_NEW_H
  2 #define _DEBUG_NEW_H
  3 
  4 #include <new>
  5 
  6 /* Prototypes */
  7 bool check_leaks();
  8 void* operator new(size_t size, const char* file, int line);
  9 void* operator new[](size_t size, const char* file, int line);
 10 #ifndef NO_PLACEMENT_DELETE
 11 void operator delete(void* pointer, const char* file, int line);
 12 void operator delete[](void* pointer, const char* file, int line);
 13 #endif // NO_PLACEMENT_DELETE
 14 void operator delete[](void*);    // MSVC 6 requires this declaration
 15 
 16 /* Macros */
 17 #ifndef DEBUG_NEW_NO_NEW_REDEFINITION
 18 #define new DEBUG_NEW
 19 #define DEBUG_NEW new(__FILE__, __LINE__)
 20 #define debug_new new
 21 #else
 22 #define debug_new new(__FILE__, __LINE__)
 23 #endif // DEBUG_NEW_NO_NEW_REDEFINITION
 24 #ifdef DEBUG_NEW_EMULATE_MALLOC
 25 #include <stdlib.h>
 26 #define malloc(s) ((void*)(debug_new char[s]))
 27 #define free(p) delete[] (char*)(p)
 28 #endif // DEBUG_NEW_EMULATE_MALLOC
 29 
 30 /* Control flags */
 31 extern bool new_verbose_flag;    // default to false: no verbose information
 32 extern bool new_autocheck_flag;    // default to true: call check_leaks() on exit
 33 
 34 #endif // _DEBUG_NEW_H
 35 
 36 
 37 /*
 38  * debug_new.cpp  1.11 2003/07/03
 39  *
 40  * Implementation of debug versions of new and delete to check leakage
 41  *
 42  * By Wu Yongwei
 43  *
 44  */
 45 
 46 #include <new>
 47 #include <stdio.h>
 48 #include <stdlib.h>
 49 
 50 #ifdef _MSC_VER
 51 #pragma warning(disable: 4073)
 52 #pragma init_seg(lib)
 53 #endif
 54 
 55 #ifndef DEBUG_NEW_HASHTABLESIZE
 56 #define DEBUG_NEW_HASHTABLESIZE 16384
 57 #endif
 58 
 59 #ifndef DEBUG_NEW_HASH
 60 #define DEBUG_NEW_HASH(p) (((unsigned)(p) >> 8) % DEBUG_NEW_HASHTABLESIZE)
 61 #endif
 62 
 63 // The default behaviour now is to copy the file name, because we found
 64 // that the exit leakage check cannot access the address of the file
 65 // name sometimes (in our case, a core dump will occur when trying to
 66 // access the file name in a shared library after a SIGINT).
 67 #ifndef DEBUG_NEW_FILENAME_LEN
 68 #define DEBUG_NEW_FILENAME_LEN    20
 69 #endif
 70 #if DEBUG_NEW_FILENAME_LEN == 0 && !defined(DEBUG_NEW_NO_FILENAME_COPY)
 71 #define DEBUG_NEW_NO_FILENAME_COPY
 72 #endif
 73 #ifndef DEBUG_NEW_NO_FILENAME_COPY
 74 #include <string.h>
 75 #endif
 76 
 77 struct new_ptr_list_t
 78 {
 79     new_ptr_list_t*        next;
 80 #ifdef DEBUG_NEW_NO_FILENAME_COPY
 81     const char*            file;
 82 #else
 83     char                file[DEBUG_NEW_FILENAME_LEN];
 84 #endif
 85     int                    line;
 86     size_t                size;
 87 };
 88 
 89 static new_ptr_list_t* new_ptr_list[DEBUG_NEW_HASHTABLESIZE];
 90 
 91 bool new_verbose_flag = false;
 92 bool new_autocheck_flag = true;
 93 
 94 bool check_leaks()
 95 {
 96     bool fLeaked = false;
 97     for (int i = 0; i < DEBUG_NEW_HASHTABLESIZE; ++i)
 98     {
 99         new_ptr_list_t* ptr = new_ptr_list[i];
100         if (ptr == NULL)
101             continue;
102         fLeaked = true;
103         while (ptr)
104         {
105             printf("Leaked object at %p (size %u, %s:%d)/n",
106                     (char*)ptr + sizeof(new_ptr_list_t),
107                     ptr->size,
108                     ptr->file,
109                     ptr->line);
110             ptr = ptr->next;
111         }
112     }
113     if (fLeaked)
114         return true;
115     else
116         return false;
117 }
118 
119 void* operator new(size_t size, const char* file, int line)
120 {
121     size_t s = size + sizeof(new_ptr_list_t);
122     new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s);
123     if (ptr == NULL)
124     {
125         fprintf(stderr, "new:  out of memory when allocating %u bytes/n",
126                 size);
127         abort();
128     }
129     void* pointer = (char*)ptr + sizeof(new_ptr_list_t);
130     size_t hash_index = DEBUG_NEW_HASH(pointer);
131     ptr->next = new_ptr_list[hash_index];
132 #ifdef DEBUG_NEW_NO_FILENAME_COPY
133     ptr->file = file;
134 #else
135     strncpy(ptr->file, file, DEBUG_NEW_FILENAME_LEN - 1);
136     ptr->file[DEBUG_NEW_FILENAME_LEN - 1] = '/0';
137 #endif
138     ptr->line = line;
139     ptr->size = size;
140     new_ptr_list[hash_index] = ptr;
141     if (new_verbose_flag)
142         printf("new:  allocated  %p (size %u, %s:%d)/n",
143                 pointer, size, file, line);
144     return pointer;
145 }
146 
147 void* operator new[](size_t size, const char* file, int line)
148 {
149     return operator new(size, file, line);
150 }
151 
152 void* operator new(size_t size)
153 {
154     return operator new(size, "<Unknown>", 0);
155 }
156 
157 void* operator new[](size_t size)
158 {
159     return operator new(size);
160 }
161 
162 void* operator new(size_t size, const std::nothrow_t&) throw()
163 {
164     return operator new(size);
165 }
166 
167 void* operator new[](size_t size, const std::nothrow_t&) throw()
168 {
169     return operator new[](size);
170 }
171 
172 void operator delete(void* pointer)
173 {
174     if (pointer == NULL)
175         return;
176     size_t hash_index = DEBUG_NEW_HASH(pointer);
177     new_ptr_list_t* ptr = new_ptr_list[hash_index];
178     new_ptr_list_t* ptr_last = NULL;
179     while (ptr)
180     {
181         if ((char*)ptr + sizeof(new_ptr_list_t) == pointer)
182         {
183             if (new_verbose_flag)
184                 printf("delete: freeing  %p (size %u)/n", pointer, ptr->size);
185             if (ptr_last == NULL)
186                 new_ptr_list[hash_index] = ptr->next;
187             else
188                 ptr_last->next = ptr->next;
189             free(ptr);
190             return;
191         }
192         ptr_last = ptr;
193         ptr = ptr->next;
194     }
195     fprintf(stderr, "delete: invalid pointer %p/n", pointer);
196     abort();
197 }
198 
199 void operator delete[](void* pointer)
200 {
201     operator delete(pointer);
202 }
203 
204 // Some older compilers like Borland C++ Compiler 5.5.1 and Digital Mars
205 // Compiler 8.29 do not support placement delete operators.
206 // NO_PLACEMENT_DELETE needs to be defined when using such compilers.
207 // Also note that in that case memory leakage will occur if an exception
208 // is thrown in the initialization (constructor) of a dynamically
209 // created object.
210 #ifndef NO_PLACEMENT_DELETE
211 void operator delete(void* pointer, const char* file, int line)
212 {
213     if (new_verbose_flag)
214         printf("info: exception thrown on initializing object at %p (%s:%d)/n",
215                 pointer, file, line);
216     operator delete(pointer);
217 }
218 
219 void operator delete[](void* pointer, const char* file, int line)
220 {
221     operator delete(pointer, file, line);
222 }
223 
224 void operator delete(void* pointer, const std::nothrow_t&)
225 {
226     operator delete(pointer, "<Unknown>", 0);
227 }
228 
229 void operator delete[](void* pointer, const std::nothrow_t&)
230 {
231     operator delete(pointer, std::nothrow);
232 }
233 #endif // NO_PLACEMENT_DELETE
234 
235 // Proxy class to automatically call check_leaks if new_autocheck_flag is set
236 class new_check_t
237 {
238 public:
239     new_check_t() {}
240     ~new_check_t()
241     {
242         if (new_autocheck_flag)
243         {
244             // Check for leakage.
245             // If any leaks are found, set new_verbose_flag so that any
246             // delete operations in the destruction of global/static
247             // objects will display information to compensate for
248             // possible false leakage reports.
249             if (check_leaks())
250                 new_verbose_flag = true;
251         }
252     }
253 };
254 static new_check_t new_check_object; 
View Code

内存跟踪检测:boost库(来源:http://blog.csdn.net/zmyer/article/details/21475101)

  1 #include<stdio.h>
  2 #include<map>
  3 #include<boost/thread/mutex.hpp>
  4 #include<boost/thread/locks.hpp>
  5 using namespace boost;
  6 
  7 #define MEM_CHECK_TABLESIZE 1024*1024
  8 #define MEM_HASH_FUNC(ptr) ((reinterpret_cast<unsigned long>(ptr))%MEM_CHECK_TABLESIZE)
  9 #define MEM_FILENAME_SIZE 1024
 10 
 11 boost::mutex mut;
 12 boost::mutex mem_mut;
 13 struct allocMem_ptr_t
 14 {
 15     allocMem_ptr_t()
 16     {
 17         bzero(fileName,sizeof(fileName));
 18         size = 0;
 19         line = 0;
 20         next = NULL;
 21     }
 22     char fileName[MEM_FILENAME_SIZE];
 23     int size;
 24     int line;
 25     allocMem_ptr_t* next;
 26 };
 27 
 28 struct allocMem_ptr_t* allocMem_list[MEM_CHECK_TABLESIZE];
 29 int tableSize = 0;
 30 
 31 struct memLeak_ptr_t
 32 {
 33     memLeak_ptr_t()
 34     {
 35         bzero(fileName,sizeof(fileName));
 36         size = 0;
 37     }
 38     char fileName[MEM_FILENAME_SIZE];
 39     int size;
 40 };
 41 std::map<int,memLeak_ptr_t> memLeak_map;
 42 void memCheck()
 43 {
 44     size_t index = 0;
 45     mem_mut.lock();
 46     for(int i=0;i<MEM_CHECK_TABLESIZE;i++)
 47     {
 48         allocMem_ptr_t* alloc = allocMem_list[i];
 49         if(NULL == alloc) continue;
 50         while(alloc)
 51         {
 52             memLeak_ptr_t memLeak;
 53             sprintf(memLeak.fileName,"%s:%d",alloc->fileName,alloc->line);
 54             memLeak.size = alloc->size;
 55             memLeak_map.insert(std::make_pair(index,memLeak));
 56             alloc = alloc->next;
 57             index++;
 58         }
 59     }
 60     mem_mut.unlock();
 61     std::map<std::string,int> leakCount;
 62     for(int i =0;i<memLeak_map.size();i++)
 63         leakCount[memLeak_map[i].fileName] += memLeak_map[i].size;
 64     typedef std::map<std::string,int>::iterator leakCount_iter;
 65     for(leakCount_iter iter = leakCount.begin();iter != leakCount.end();++iter)
 66     {
 67         printf("%s LEAK MEMORY SIZE:%d\n",iter->first.c_str(),iter->second);
 68     }
 69 }
 70 void* operator new(size_t size,const char* file,int line)
 71 {
 72     size_t siz = size + sizeof(allocMem_ptr_t);
 73     allocMem_ptr_t* ptr = (allocMem_ptr_t*)::malloc(siz);
 74     if(NULL == ptr) abort();
 75     void* p = (char*)ptr + sizeof(allocMem_ptr_t);
 76     strncpy(ptr->fileName,file,MEM_FILENAME_SIZE-1);
 77     ptr->size = size;
 78     ptr->line = line;
 79 
 80     mem_mut.lock();
 81     size_t index = MEM_HASH_FUNC(p);
 82     ptr->next = allocMem_list[index];
 83     allocMem_list[index] = ptr;
 84     ++tableSize;
 85     mem_mut.unlock();
 86     return p;
 87 }
 88 
 89 void* operator new[](size_t size,const char* file,int line)
 90 {
 91     return operator new(size,file,line);
 92 }
 93 
 94 void operator delete(void* ptr)
 95 {
 96     if(NULL == ptr) return;
 97     allocMem_ptr_t* pre = NULL;
 98     size_t index = MEM_HASH_FUNC(ptr);
 99     mem_mut.lock();
100     allocMem_ptr_t* pointer = allocMem_list[index];
101     while(pointer)
102     {
103         if((char*)pointer + sizeof(allocMem_ptr_t) == ptr)
104         {
105             if(NULL == pre)
106                 allocMem_list[index] = pointer->next;
107             else
108                 pre->next = pointer->next;
109             --tableSize;
110             break;
111         }
112         pre = pointer;
113         pointer = pointer->next;
114     }
115     mem_mut.unlock();
116     free(pointer);
117 }
118 
119 void operator delete[](void* pointer)
120 {
121     operator delete(pointer);
122 }
123 
124 void operator delete(void* pointer,const char* file,int line)
125 {
126     operator delete(pointer);
127 }
128 void operator delete[](void* pointer,const char* file,int line)
129 {
130     operator delete(pointer);
131 }
View Code

 

posted on 2014-03-21 15:01  Eahom  阅读(1479)  评论(0)    收藏  举报