下面介绍用重载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,还需要注意放置的顺序。
 
到这里这个简易的内存泄露检测工具完成了,但目前还不能用于多线程。

①当两个operator new和operator delete有相等的参数个数,并且除了第一个参数之外其余参数的类型依次完全相同之时,我们称它们为一对匹配的operator new和operator delete。
  不过正常情况下带多个参数的delete不会被调用,只有在构建一个对象的过程中,构造函数中发生异常,并且这个异常被捕获了,那么此时C++的异常处理机制才会自动用与被使用的operator new匹配的operator delete来释放内存(补充一点:在operator new中抛出异常不会导致这样的动作,因为系统认为这标志着内存分配失败)。
  试验代码:
    #include <malloc.h>
    struct Base
    {
        Base()
        {
            throw int(3);
        }
        ~Base() {}
        void* operator new( size_t nSize, const char*,int)
        {
            void* p = malloc( nSize );
            return p;
        }
        void operator delete( void *p)
        {
            free(p);
        }
        void operator delete( void* p,const char*,int)
        {
            free( p );
        }
    };
    #define new new(__FILE__, __LINE__)
    int main( void )
    {
        Base* p = null;
        try
        {
            p = new Base;
            delete p;
        }
        catch(...)
        {
        }
        return 0;
    }

重载全局new/delete实现内存检测的更多相关文章

  1. C++:重载全局new/delete实现跨平台多线程内存检测

    Reference: https://blog.csdn.net/u014023615/article/details/39551191 Reference: https://blog.csdn.ne ...

  2. [C++] 重载new和delete——控制内存分配

      1.new和delete表达式的工作机理      1)new表达式实际执行了三步 string *sp=new string("aaaa"); ];//string采用默认初 ...

  3. 重载operator new delete函数

    可以重载global的operator new delete 函数,细节如下: MyNewDelete.h #pragma once #include <stdlib.h> #includ ...

  4. 重载new和delete来检测内存泄漏

    重载new和delete来检测内存泄漏 1. 简述 内存泄漏属于资源泄漏的一种,百度百科将内存泄漏分为四种:常发性内存泄漏.偶发性内存泄漏.一次性内存泄漏和隐式内存泄漏.    常发性指:内存泄漏的代 ...

  5. ZT c++ 中的重载全局new,delete

    c++ 中的重载全局new,delete 分类: c++ 2010-08-06 10:31 116人阅读 评论(1) 收藏 举报 deletec++file编译器语言工作 最近做一个小项目,对c++又 ...

  6. 【ThinkingInC++】64、重载new和delete,来模仿内存的分配

    /** * 书本:[ThinkingInC++] * 功能:重载new和delete.来模仿内存的分配 * 时间:2014年10月5日14:30:11 * 作者:cutter_point */ #in ...

  7. C++ 重载new和delete操作符

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

  8. 重载new和delete

    当我们创建一个new表达式时,会发生两件事.首先使用operator new()分配内存,然后调用构造函数.在delete表达式里,调用了析构函数,然后使用operator delete()释放内存. ...

  9. c/c++ 重载new,delete运算符 placement new

    重载new,delete运算符 new,delete在c++中也被归为运算符,所以可以重载它们. new的行为: 先开辟内存空间 再调用类的构造函数 开辟内存空间的部分,可以被重载. delete的行 ...

随机推荐

  1. 在Maven仓库中添加Oracle数据库的JDBC驱动依赖

    在使用idea连接oracle数据库时发现直接添加oracle依赖 <dependency><groupId>com.oracle</groupId><art ...

  2. 倒计时5,4,3,2,1css实现(count down from 5 to 1 using css)

    //count down from 5 to 1, a useful animation. show the code to you:   <!DOCTYPE html> <html ...

  3. Tab Key not working when using Xfce remote desktop

    Xfce 远程桌面Tab键设置 Use CTRL-tab instead of  tab The XFCE Terminal has kidnapped the tab key for a featu ...

  4. 例如android:layout_marginBottom的值为负数

    为什么有时候像android:layout_marginBottom等变量的赋值为负数? 例如如下代码: <?xml version="1.0" encoding=" ...

  5. 如何监视和更新 Azure 中的 Linux 虚拟机

    为确保 Azure 中的虚拟机 (VM) 正常运行,可以查看启动诊断.性能指标,并管理程序包更新. 本教程介绍如何执行下列操作: 在 VM 上启用启动诊断 查看启动诊断 在 VM 上启用诊断扩展 基于 ...

  6. Oracle EBS 数据访问权限集

    SELECT frv.responsibility_name, fpo.profile_option_name, fpo.user_profile_option_name, fpv.profile_o ...

  7. SQL Server配置数据库邮件

    需求描述 在生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,可以以发邮件告知,邮件作为一种非常便利的预警实现方式,在及时性和易用性方面也有着不可替 ...

  8. .net通用类型转换方法

    由于数据类型多,要按照逐个类型写一个类型转换的方法的话一是代码量多,显得累赘. using System; using System.ComponentModel; using System.Glob ...

  9. mysql(5.7.17)字符集设置(character_set/collation)

    0 查看字符集(character_set/collation) use information_schema;desc tables;    --一定记住tables表,information_sc ...

  10. 如何获取UITableView中cell的frame值

    如何获取UITableView中cell的frame值 这个可以用来处理UITableView弹出键盘的问题 本人视频教程系类   iOS中CALayer的使用 效果: 源码: // // ViewC ...