• 重载operator new实现检测内存泄漏是否可行


      行与不行,就凭我这水平,说出来未免显示太过自大。不还,我还想根据自己的代码来讨论这个问题。

      重载operator new来检测内存只的办法,那就是在new的时候记录指针地址及文件名、行号,在delete的时候取消记录。到最后程序结束,还有哪些指针未释放,则为泄漏。

      第一步,你得重载operator new,或者也可以重写。在http://www.cplusplus.com/reference/new/operator%20new/中指明new有三种形式,因为我们还分配数组,故还有new[]这个函数也要重载。那么有6种。原文中指明“The allocating versions ((1) and (2)) are also replaceable:”,则说明我们只能重载4个函数(也必须,不然检测不到部分内存分配,没有意义)。由于placement new不会有内存泄漏,也不能重载,可以不管。

    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    inline void *operator new[](std::size_t size, const char *file, int line)
    {
        std::cout << "memory allocate at " << file << " line " << line << std::endl;
        void *p = ::operator new(size);// operator new (size,std::nothrow)
        return p;
    }
    
    inline void * operator new(std::size_t size, const char *file, int line)
    {
        std::cout << "memory allocate at " << file << " line " << line << std::endl;
        void *p = ::operator new(size);
        return p;
    }
    
    inline void operator delete(void *p)
    {
        std::cout << "free" << std::endl;
        free(p);
    }
    
    inline void operator delete[] (void *p)
    {
        std::cout << "free[]" << std::endl;
        free(p);
    }
    
    #define new new(__FILE__, __LINE__)
    
    class  TTest
    {
    public:
        TTest(){ std::cout << "construct...." << std::endl; }
        ~TTest(){ std::cout << "destruct...." << std::endl; }
    };
    
    int main()
    {
        TTest *p = new TTest();
        delete p;
    
        return 0;
    }
    View Code

    注意上面的代码中,因为懒,并没有重载完4个函数。另外,注意new函数是重载,故可以调用::operator new,而delete函数是重写,再调::operator delete就递归成死循环了。不过这并不影响我说明问题。

    结果:

    memory allocate at ../test/main.cpp line 61
    construct....
    destruct....
    free
    按 <RETURN> 来关闭窗口...

    看,已经知道分配的文件、行号,还能知道是否已分配,那么说明还是可行的。

      可是,并不是所有的程序都是这么简单的。重载后,我们当然希望所来new的用法及参数都不用变。因为我们不希望已写的代码需要修改。从另一个方面说,如果用了第三方库,总不能一个个将别人的new替换成自己的函数。于是有了“#define new new(__FILE__, __LINE__)”这行代码,通过一个宏定义巧妙地将函数替换了。

    new int()被替换成new(__FUNCTION__,__LINE__) int(),这样,原来的代码不变。但是,这个宏定义并不够巧妙。上面提到,new有三种形式,这个宏定义只能替换最常用的一种void* operator new (std::size_t size) throw (std::bad_alloc);对于其他则无能为力。

    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    
    inline void *operator new[](std::size_t size, const char *file, int line)
    {
        std::cout << "memory allocate at " << file << " line " << line << std::endl;
        void *p = ::operator new(size);// operator new (size,std::nothrow)
        return p;
    }
    
    inline void * operator new(std::size_t size, const char *file, int line)
    {
        std::cout << "memory allocate at " << file << " line " << line << std::endl;
        void *p = ::operator new(size);
        return p;
    }
    
    inline void operator delete(void *p)
    {
        std::cout << "free" << std::endl;
        free(p);
    }
    
    inline void operator delete[] (void *p)
    {
        std::cout << "free[]" << std::endl;
        free(p);
    }
    
    #define new new(__FILE__, __LINE__)
    
    class  TTest
    {
    public:
        TTest(){ std::cout << "construct...." << std::endl; }
        ~TTest(){ std::cout << "destruct...." << std::endl; }
    };
    
    int main()
    {
        char *buff[10240] = {''};
        TTest *p = new TTest();
        delete p;
    
        p = new(buff) TTest();
    
        return 0;
    }
    View Code

    显然,p = new(buff) TTest();调用了第三种new函数void* operator new (std::size_t size, void* ptr) throw();由于参数问题编译报错。其实,第二、三种new函数原型在STL、BOOST里很常用。所以这种替换并不适用。

      由于我并不知道编译器#define new new(__FILE__, __LINE__)是怎么去解释这行代码的,故没法写出一个实现三种函数原型都能替换的宏定义。当然,如果你只想知道有没有内存泄漏,不需要知道文件名、行号,则重写new函数而不是重载是可行的。但感觉这也太鸡肋了。

      不知道有没有大神能实现函数的替换,望指教。

  • 相关阅读:
    1.Oracle实例和Oracle数据库(Oracle体系结构)
    04.SQL基础-->分组与分组函数
    SYSAUX表空间满的解决方法
    Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
    Python学习-八周五次课(12月15日)
    ELK安装
    Python学习-八周二次课(12月12日)
    Python学习-八周一次课(12月11日)
    Python学习——七周四次课(12月7日)
    Python学习-复习7次课(12月4日)
  • 原文地址:https://www.cnblogs.com/coding-my-life/p/3985164.html
Copyright © 2020-2023  润新知