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

 

你可能感兴趣的:(delete)