`

重载全局new/delete实现内存检测

 
阅读更多
转自
http://blog.csdn.net/hzyong_c/article/details/5949314


    下面介绍用重载new/delete运算符的方式来实现一个简单的内存泄露检测工具,基本思想是重载全局new/delete运算符,被检测代码调用new和delete运算符时就会调用重载过的operator new和operator delete,在重载的operator new里和operator delete里记录下内存申请和释放信息,从而判断内存使用情况。

    下面一步步介绍它的实现!
    1、  全局new/delete的重载 
    先看一下重载new/delete的规则:
重载的operator new的参数个数任意,但第一个参数必须是size_t类型的,返回值必须是void*。重载operator delete只允许有一个参数,且是void*型。
当然,不光要重载operator new 和 operator delete, 还要重载operator new [], operator delete [],更多operator new和operator delete重载的内容参考《Effective C++》
重载的new/delete, new[]/delete[]代码如下:
void * operator new (size_t size){
if(0 == size){
        return 0;
}
void *p = malloc(size);
return p;
}
 
void * operator new [](size_t size){
return operator new(size);
}
 
void operator delete (void * pointer){
if(0 != pointer){
free(pointer);
}
}
 
void operator delete[](void * pointer){
       operator delete(pointer);
}


2、  用__FILE__, __LINE__记录new的位置
为了找到内存泄露的元凶,我要记录下每一处new所在的文件名和所在行。于是再次重载了operator new:
void * operator new (size_t size, const char* file, const size_t line);
void * operator new [](size_t size, const char* file, const size_t line);

为了避免编译时出现warning C4291(没有与operator new(unsigned int,const char *,const unsigned int) 匹配的delete),又重载了
void operator delete (void * pointer, const char* file, const size_t line);
void operator delete[](void * pointer, const char* file, const size_t line);

              尽管我知道它没用。
    我想到了用系统提供的__FILE__和 __LINE__宏获取当前文件名与行号,我试图把__FILE__和 __LINE__直接填到operator new和operator new[]函数体里边,然后把函数置成inline,结果都输出的是重载operator new和operator new[]的文件和函数体printf函数所在行。然后又试了将operator new的缺省参数设为__FILE__和 __LINE__结果依然,于是想到了用宏定义。
先看看MFC里的做法,MFC为了调试方便,对new进行了宏定义:
#define new DEBUG_NEW
#define DEBUG_NEW new(THIS_FILE, __LINE__)


这里我借用MFC的做法,我也用宏定义:
void * operator new (size_t size, const char* file, const size_t line);
void * operator new [](size_t size, const char* file, const size_t line);
#define MC_NEW new(__FILE__, __LINE__)
#define new MC_NEW


3、  将malloc/free 用new/delete替换
为了便于统计malloc/free信息,也用宏定义的方法处理:
#define malloc(s) ((void*)new unsigned char[s])
#define free(p)   (delete [] (char*)(p));


4、  在数据结构里存储内存使用情况。
            下面写一个用于存储new/delete中内存信息的数据结构,可以使用链表,也可以使用哈希表,这里选用哈希表,写一个CHash类。
代码略。

5、  为了保证CHash在所有对象析构执行完之后再销毁,应该将CHash放在全局存储区,将其设成static类型,另外,如果有多个static,还需要注意放置的顺序。

到这里这个简易的内存泄露检测工具完成了,但目前还不能用于多线程。
分享到:
评论

相关推荐

    自定义数据new/delete源码

    标题中的“自定义数据new/delete源码”指的是程序员根据特定需求重载或替换C++内置的`new`和`delete`,以实现自定义的内存分配策略。这样做可以提供额外的功能,如日志记录、资源池管理、异常处理等。 `new`运算符...

    source_delete_new.rar_hook delete_内存泄露_重载new

    结合以上两种方法,当`new`和`delete`被重载并配合钩子函数使用时,我们可以实现对内存分配的全面监控,例如,在分配内存时记录分配信息,在释放内存时检查是否所有分配的内存都已被释放。如果发现有未释放的内存,...

    重载new 用法例子

    1. **重载的语法**:在C++中,你可以通过在类的作用域或全局作用域内定义`operator new`和`operator delete`函数来实现`new`的重载。例如: ```cpp void* operator new(size_t size) { // 自定义内存分配逻辑 } ...

    深入理解C++中的new/delete和malloc/free动态内存管理及区别介绍

    从底层实现上看,`new`和`delete`实际上是通过重载`operator new`和`operator delete`这两个全局操作符来实现的。例如,`new`操作符通常会调用`operator new`,在内存分配失败时,可能还会尝试调用 `_callnewh` 函数...

    检测内存泄露的工具

    本文将详细介绍一种名为`debugnew`的内存泄露检测工具,它通过重载`new`和`delete`操作符,帮助开发者定位内存泄露的位置。 #### 工具原理与使用 `debugnew`的核心机制在于重载`new`和`delete`操作符,以便在内存...

    C++中对使用malloc/new引起的内存泄露的检查

    例如,我们可以创建一个全局的分配器类,包含一个静态成员变量来记录分配的内存总数,并在`new`和`delete`操作中更新这个计数。 ```cpp class CustomAllocator { public: void* operator new(size_t size) { void...

    关于new和delete的详细用法

    6. 全局的operator new也是可以重载的,但这样一来就不能再递归的使用new来分配内存,而只能使用malloc了。例如,void* operator new(size_t size){ printf("global newn"); return malloc(size);} 7. delete也有...

    内存泄漏检查类

    本话题主要探讨的是如何在C++中进行内存泄漏的检查,通过重载全局的`new/delete`以及`new[]/delete[]`操作符来实现。下面我们将深入讲解这个主题。 首先,了解内存泄漏的基本概念。内存泄漏是指程序在申请内存后,...

    c++检测内存泄漏(如何检测内存泄漏)

    在描述的案例中,我们可能使用的是动态分析的一种,即通过重载全局或局部的`new`和`delete`运算符来追踪内存分配与释放。 首先,我们要理解`new`和`delete`运算符的作用。`new`用于动态分配内存,而`delete`用于...

    C++ new、delete(new[]、delete[])操作符重载需要注意的问题

    2. **全局与类内重载的影响**:全局`new`和`delete`重载会改变所有默认的内存分配行为,可能导致链接错误如果多个库有相同重载。类内的重载仅影响该类及其派生类,但需注意成员函数的继承性。若只想为特定类提供...

    自己写的一个内存管理pool

    在这个场景中,我们关注的是一个自定义的内存管理池(内存池),这是通过重载`new`运算符实现的。下面将详细讨论这个主题。 内存池是一种预先分配一大块内存并按需分配小块内存的技术。这种方法可以避免系统频繁地...

    cpp代码-只能创建栈对象 做法:将operator new/delete设置为私有的

    实现这一策略的一种方法是重载`operator new`和`operator delete`并将其声明为私有。 首先,让我们理解`operator new`和`operator delete`的作用。它们是C++中的全局运算符,负责动态内存分配和释放。`operator new...

    C++内存管理

    - 可以通过重载全局的`new`和`delete`操作符来控制整个程序中所有对象的内存分配和释放过程。这种方式适用于所有类型的数据,包括基本类型和自定义类型。 2. **为单个的类重载new[]和delete[]操作符** - 当需要...

    C++内存管理技术内幕

    - **重载全局的new和delete操作符**:为了实现自定义的内存管理策略,可以重载new和delete,提供自定义的内存分配和释放逻辑,如记录内存使用情况、优化内存碎片等。 - **为单个的类重载new[]和delete[]**:当需要...

    memroy.zip

    new,delete的重载函数,可以是全局函数,也可以是类内部的公有重载函数;当既有全局的重载函数,也有类内部的公有重载函数时,实际调用的是类内部的公有重载函数。 new,delete可以有多种重载方式,但是,new函数的...

    C++内存泄露 是啊 艾丝凡阿萨

    实现这个内存检测器的关键在于重载`new`和`delete`操作符。重载`new`操作符的目的是在分配内存时记录分配的详细信息,如文件名、行号、分配的指针和大小。同样,重载`delete`操作符是为了在释放内存时更新记录,确保...

    有效的C 内存泄露检测方法1

    此外,通过重载`new`和`delete`,能够在不改变原有代码的情况下,实现对内存泄漏的自动化检测。 总的来说,有效的内存泄漏检测对于确保C++程序的健康运行至关重要。本文的方法提供了一种实用的解决方案,帮助开发者...

    深入C++的new关键字

    全局的operator new也是可以重载的,但这样一来就不能再递归的使用new来分配内存,而只能使用malloc了。 6. placement new的使用 placement new是用来实现定位构造的,可以在指定内存地址上用指定类型的构造函数来...

Global site tag (gtag.js) - Google Analytics