C++ 重载new和delete操作符
原因:
好处:
C++标准规定:
备注:
实现:
简单实现
void* operator new(size_t size)
{
if (size < )
return ;
if (size == )
size = ; void *res = malloc(size);
return res;
} void operator delete(void* p)
{
if (p != )
free(p);
} void* operator new[](size_t size)
{
return operator new(size);
} void operator delete[](void* src)
{
operator delete(src);
}
跨平台实现及其内存检测:(来源:http://www.linuxidc.com/Linux/2011-07/39154p4.htm)
#ifndef _DEBUG_NEW_H
#define _DEBUG_NEW_H #include <new> /* Prototypes */
bool check_leaks();
void* operator new(size_t size, const char* file, int line);
void* operator new[](size_t size, const char* file, int line);
#ifndef NO_PLACEMENT_DELETE
void operator delete(void* pointer, const char* file, int line);
void operator delete[](void* pointer, const char* file, int line);
#endif // NO_PLACEMENT_DELETE
void operator delete[](void*); // MSVC 6 requires this declaration /* Macros */
#ifndef DEBUG_NEW_NO_NEW_REDEFINITION
#define new DEBUG_NEW
#define DEBUG_NEW new(__FILE__, __LINE__)
#define debug_new new
#else
#define debug_new new(__FILE__, __LINE__)
#endif // DEBUG_NEW_NO_NEW_REDEFINITION
#ifdef DEBUG_NEW_EMULATE_MALLOC
#include <stdlib.h>
#define malloc(s) ((void*)(debug_new char[s]))
#define free(p) delete[] (char*)(p)
#endif // DEBUG_NEW_EMULATE_MALLOC /* Control flags */
extern bool new_verbose_flag; // default to false: no verbose information
extern bool new_autocheck_flag; // default to true: call check_leaks() on exit #endif // _DEBUG_NEW_H /*
* debug_new.cpp 1.11 2003/07/03
*
* Implementation of debug versions of new and delete to check leakage
*
* By Wu Yongwei
*
*/ #include <new>
#include <stdio.h>
#include <stdlib.h> #ifdef _MSC_VER
#pragma warning(disable: 4073)
#pragma init_seg(lib)
#endif #ifndef DEBUG_NEW_HASHTABLESIZE
#define DEBUG_NEW_HASHTABLESIZE 16384
#endif #ifndef DEBUG_NEW_HASH
#define DEBUG_NEW_HASH(p) (((unsigned)(p) >> 8) % DEBUG_NEW_HASHTABLESIZE)
#endif // The default behaviour now is to copy the file name, because we found
// that the exit leakage check cannot access the address of the file
// name sometimes (in our case, a core dump will occur when trying to
// access the file name in a shared library after a SIGINT).
#ifndef DEBUG_NEW_FILENAME_LEN
#define DEBUG_NEW_FILENAME_LEN 20
#endif
#if DEBUG_NEW_FILENAME_LEN == 0 && !defined(DEBUG_NEW_NO_FILENAME_COPY)
#define DEBUG_NEW_NO_FILENAME_COPY
#endif
#ifndef DEBUG_NEW_NO_FILENAME_COPY
#include <string.h>
#endif struct new_ptr_list_t
{
new_ptr_list_t* next;
#ifdef DEBUG_NEW_NO_FILENAME_COPY
const char* file;
#else
char file[DEBUG_NEW_FILENAME_LEN];
#endif
int line;
size_t size;
}; static new_ptr_list_t* new_ptr_list[DEBUG_NEW_HASHTABLESIZE]; bool new_verbose_flag = false;
bool new_autocheck_flag = true; bool check_leaks()
{
bool fLeaked = false;
for (int i = ; i < DEBUG_NEW_HASHTABLESIZE; ++i)
{
new_ptr_list_t* ptr = new_ptr_list[i];
if (ptr == NULL)
continue;
fLeaked = true;
while (ptr)
{
printf("Leaked object at %p (size %u, %s:%d)/n",
(char*)ptr + sizeof(new_ptr_list_t),
ptr->size,
ptr->file,
ptr->line);
ptr = ptr->next;
}
}
if (fLeaked)
return true;
else
return false;
} void* operator new(size_t size, const char* file, int line)
{
size_t s = size + sizeof(new_ptr_list_t);
new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s);
if (ptr == NULL)
{
fprintf(stderr, "new: out of memory when allocating %u bytes/n",
size);
abort();
}
void* pointer = (char*)ptr + sizeof(new_ptr_list_t);
size_t hash_index = DEBUG_NEW_HASH(pointer);
ptr->next = new_ptr_list[hash_index];
#ifdef DEBUG_NEW_NO_FILENAME_COPY
ptr->file = file;
#else
strncpy(ptr->file, file, DEBUG_NEW_FILENAME_LEN - );
ptr->file[DEBUG_NEW_FILENAME_LEN - ] = '/0';
#endif
ptr->line = line;
ptr->size = size;
new_ptr_list[hash_index] = ptr;
if (new_verbose_flag)
printf("new: allocated %p (size %u, %s:%d)/n",
pointer, size, file, line);
return pointer;
} void* operator new[](size_t size, const char* file, int line)
{
return operator new(size, file, line);
} void* operator new(size_t size)
{
return operator new(size, "<Unknown>", );
} void* operator new[](size_t size)
{
return operator new(size);
} void* operator new(size_t size, const std::nothrow_t&) throw()
{
return operator new(size);
} void* operator new[](size_t size, const std::nothrow_t&) throw()
{
return operator new[](size);
} void operator delete(void* pointer)
{
if (pointer == NULL)
return;
size_t hash_index = DEBUG_NEW_HASH(pointer);
new_ptr_list_t* ptr = new_ptr_list[hash_index];
new_ptr_list_t* ptr_last = NULL;
while (ptr)
{
if ((char*)ptr + sizeof(new_ptr_list_t) == pointer)
{
if (new_verbose_flag)
printf("delete: freeing %p (size %u)/n", pointer, ptr->size);
if (ptr_last == NULL)
new_ptr_list[hash_index] = ptr->next;
else
ptr_last->next = ptr->next;
free(ptr);
return;
}
ptr_last = ptr;
ptr = ptr->next;
}
fprintf(stderr, "delete: invalid pointer %p/n", pointer);
abort();
} void operator delete[](void* pointer)
{
operator delete(pointer);
} // Some older compilers like Borland C++ Compiler 5.5.1 and Digital Mars
// Compiler 8.29 do not support placement delete operators.
// NO_PLACEMENT_DELETE needs to be defined when using such compilers.
// Also note that in that case memory leakage will occur if an exception
// is thrown in the initialization (constructor) of a dynamically
// created object.
#ifndef NO_PLACEMENT_DELETE
void operator delete(void* pointer, const char* file, int line)
{
if (new_verbose_flag)
printf("info: exception thrown on initializing object at %p (%s:%d)/n",
pointer, file, line);
operator delete(pointer);
} void operator delete[](void* pointer, const char* file, int line)
{
operator delete(pointer, file, line);
} void operator delete(void* pointer, const std::nothrow_t&)
{
operator delete(pointer, "<Unknown>", );
} void operator delete[](void* pointer, const std::nothrow_t&)
{
operator delete(pointer, std::nothrow);
}
#endif // NO_PLACEMENT_DELETE // Proxy class to automatically call check_leaks if new_autocheck_flag is set
class new_check_t
{
public:
new_check_t() {}
~new_check_t()
{
if (new_autocheck_flag)
{
// Check for leakage.
// If any leaks are found, set new_verbose_flag so that any
// delete operations in the destruction of global/static
// objects will display information to compensate for
// possible false leakage reports.
if (check_leaks())
new_verbose_flag = true;
}
}
};
static new_check_t new_check_object;
内存跟踪检测:boost库(来源:http://blog.csdn.net/zmyer/article/details/21475101)
#include<stdio.h>
#include<map>
#include<boost/thread/mutex.hpp>
#include<boost/thread/locks.hpp>
using namespace boost; #define MEM_CHECK_TABLESIZE 1024*1024
#define MEM_HASH_FUNC(ptr) ((reinterpret_cast<unsigned long>(ptr))%MEM_CHECK_TABLESIZE)
#define MEM_FILENAME_SIZE 1024 boost::mutex mut;
boost::mutex mem_mut;
struct allocMem_ptr_t
{
allocMem_ptr_t()
{
bzero(fileName,sizeof(fileName));
size = ;
line = ;
next = NULL;
}
char fileName[MEM_FILENAME_SIZE];
int size;
int line;
allocMem_ptr_t* next;
}; struct allocMem_ptr_t* allocMem_list[MEM_CHECK_TABLESIZE];
int tableSize = ; struct memLeak_ptr_t
{
memLeak_ptr_t()
{
bzero(fileName,sizeof(fileName));
size = ;
}
char fileName[MEM_FILENAME_SIZE];
int size;
};
std::map<int,memLeak_ptr_t> memLeak_map;
void memCheck()
{
size_t index = ;
mem_mut.lock();
for(int i=;i<MEM_CHECK_TABLESIZE;i++)
{
allocMem_ptr_t* alloc = allocMem_list[i];
if(NULL == alloc) continue;
while(alloc)
{
memLeak_ptr_t memLeak;
sprintf(memLeak.fileName,"%s:%d",alloc->fileName,alloc->line);
memLeak.size = alloc->size;
memLeak_map.insert(std::make_pair(index,memLeak));
alloc = alloc->next;
index++;
}
}
mem_mut.unlock();
std::map<std::string,int> leakCount;
for(int i =;i<memLeak_map.size();i++)
leakCount[memLeak_map[i].fileName] += memLeak_map[i].size;
typedef std::map<std::string,int>::iterator leakCount_iter;
for(leakCount_iter iter = leakCount.begin();iter != leakCount.end();++iter)
{
printf("%s LEAK MEMORY SIZE:%d\n",iter->first.c_str(),iter->second);
}
}
void* operator new(size_t size,const char* file,int line)
{
size_t siz = size + sizeof(allocMem_ptr_t);
allocMem_ptr_t* ptr = (allocMem_ptr_t*)::malloc(siz);
if(NULL == ptr) abort();
void* p = (char*)ptr + sizeof(allocMem_ptr_t);
strncpy(ptr->fileName,file,MEM_FILENAME_SIZE-);
ptr->size = size;
ptr->line = line; mem_mut.lock();
size_t index = MEM_HASH_FUNC(p);
ptr->next = allocMem_list[index];
allocMem_list[index] = ptr;
++tableSize;
mem_mut.unlock();
return p;
} void* operator new[](size_t size,const char* file,int line)
{
return operator new(size,file,line);
} void operator delete(void* ptr)
{
if(NULL == ptr) return;
allocMem_ptr_t* pre = NULL;
size_t index = MEM_HASH_FUNC(ptr);
mem_mut.lock();
allocMem_ptr_t* pointer = allocMem_list[index];
while(pointer)
{
if((char*)pointer + sizeof(allocMem_ptr_t) == ptr)
{
if(NULL == pre)
allocMem_list[index] = pointer->next;
else
pre->next = pointer->next;
--tableSize;
break;
}
pre = pointer;
pointer = pointer->next;
}
mem_mut.unlock();
free(pointer);
} void operator delete[](void* pointer)
{
operator delete(pointer);
} void operator delete(void* pointer,const char* file,int line)
{
operator delete(pointer);
}
void operator delete[](void* pointer,const char* file,int line)
{
operator delete(pointer);
}
C++ 重载new和delete操作符的更多相关文章
- 重载new delete操作符是怎么调用的
自定义的new操作符是怎么对英语new 一个对象的?自定义的delete操作符什么情况下得到调用?new一个对象时出现异常需要我操心内存泄露吗?下面的一个例子帮我们解开所有的疑惑. 1. 调用规则 ...
- C++重载new和delete运算符
内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...
- 重载new和delete
当我们创建一个new表达式时,会发生两件事.首先使用operator new()分配内存,然后调用构造函数.在delete表达式里,调用了析构函数,然后使用operator delete()释放内存. ...
- C++学习32 重载new和delete运算符
内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...
- 重载new和delete运算符
内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...
- Javascript的变量与delete操作符
原文:http://charlee.li/javascript-variables-and-delete-operator.html 刚刚看到一篇好文(原文链接), 对Javascript中的dele ...
- javascript之delete操作符
理解delete 理论 代码段的类型 执行上下文 活动对象 / 变量对象 属性的特性 内置属性与 DontDelete 未声明的赋值 Firebug的困惑 在eval中删除变量 浏览器兼容性 Geck ...
- 【ThinkingInC++】64、重载new和delete,来模仿内存的分配
/** * 书本:[ThinkingInC++] * 功能:重载new和delete.来模仿内存的分配 * 时间:2014年10月5日14:30:11 * 作者:cutter_point */ #in ...
- 重载new和delete来检测内存泄漏
重载new和delete来检测内存泄漏 1. 简述 内存泄漏属于资源泄漏的一种,百度百科将内存泄漏分为四种:常发性内存泄漏.偶发性内存泄漏.一次性内存泄漏和隐式内存泄漏. 常发性指:内存泄漏的代 ...
随机推荐
- VS2012无法安装cocos2d-x-2.1.4 解决方法及VS2012新建coco2d-x项目(一)
转自:http://www.cnblogs.com/wangpei/admin/EditPosts.aspx?opt=1 (注:此方法是可行,仅供参考,建议大家直接看我的 一见命令解决vs安装并创建c ...
- IDEA社区版运行并发布web项目
IDEA社区版相对收费版少了很多功能,其中包括tomcat等web服务器的支持.网上大部分的IDEA web应用发布教程都是基于收费版的,社区版并没有这么直接的图形化工具可以运行或发布web应用.幸运 ...
- java 考试试题
Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他.有些题来自网上搜集整理,有些题来自学员 ...
- Winform下实现图片切换特效的方法
本文实例讲述了Winform下实现图片切换特效的方法,是应用程序开发中非常实用的一个功能.分享给大家供大家参考之用.具体方法如下: 本实例源自网络,功能较为齐全.丰富!主要功能代码如下: using ...
- 从零开始学JAVA(03)-用Eclipse生成HelloWorld的Jar文件(简单不带包)
前面已经编写了helloWorld的程序,也可以在Eclipse IDE中正常运行,但如何脱离IDE运行呢? 先通过代码生成JAR文件,选择“File→Export...”,弹出Export对话框,选 ...
- Android(java)学习笔记264:Android下的属性动画高级用法(Property Animation)
1. 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是最常用的一些用法,这些用法足以覆盖我们平时大多情况下的动画需求了.但是,正如上篇文章当中所说到的,属性动画对补间动画 ...
- No saved view state could be found for the view identifier
解决方法: javax.faces.application.ViewExpiredException:No saved view state could be found for the view i ...
- VS2013 添加文件头部注释模板
在看视频的时候发现,视频中每次新建一个类文件 都会自动生成一串 头部的注释:
- css初接触
一.简介:CSS 即 级联样式表 . 它是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言. css是能够真正做到网页表现与内容分离的一种 ...
- js的时间操作方法
1.js获取系统时间格式为YYYY-MM-DD HH:MM:SS 1 function curDateTime(){ 2 var d = new Date(); 3 var year = d.getY ...