C++
主要是针对new
/delete
运算符进行重载 ,思路和上述hook malloc
函数一样,我们可以定义一个MemCheck
类,该类用来存储内存信息,包括内存的地址,大小。如果愿意的话,还可以存储调用的位置,这里为了简化处理,就不演示了。在调用 new
运算符时,我们将申请内存的相关信息存入MemCheck
中的一个map
中,它的key
是内存地址,value
是内存大小。在调用delete
时,将该内存地址从map
中删除掉。(此处未判断double free
的问题,可以考虑下如何去做?)有兴趣的话也可以考虑一下new[]
和delete[]
的重载实现。
我们定义一个全局静态的MemCheck
类实例,这样该实例对象的析构将会在main
函数结束后才会进行,因此,我们只需要在析构函数中判断一下,map
中是否还有没有元素存在,就知道还有没有内存泄漏了。将其打印出来即可。
完整代码示例如下:
//new.cpp #include <iostream> #include <malloc.h> #include <memory> #include <map> bool new_enabled = true; class MemCheck { private: std::map<void*, size_t> MemInfo; //key 为申请内存的地址, value为申请内存的大小 public: void Allocation(void *p, size_t size){ //申请内存时将内存信息放入map new_enabled = false; MemInfo[p] = size; new_enabled = true; } void Freed(void *p) { //释放内存时将内存信息从map中移除 MemInfo.erase(p); } ~ MemCheck(){ std::cout << "Memory Not Freed:\n"; std::map<void *, size_t>::iterator it = MemInfo.begin(); while (it != MemInfo.end()) { std::cout << "\t[" << it->first << "] " << it->second << " bytes\n"; it++; } } }; static MemCheck mcheck; void *operator new(size_t size) { if (new_enabled) { void *p = malloc(size); mcheck.Allocation(p, size); return p; } else { return malloc(size); } } void operator delete(void *p) { mcheck.Freed(p); free(p); } struct Object { int x, y, z; }; void test(){ std::string str = "hello"; Object *obj = new Object; std::unique_ptr<Object> obj2(new Object()); //delete obj; } int main(void){ test(); int *pInt = new int; std::unique_ptr<int> p(new int); return 0; }
以上代码,在test
函数中,首先string
的内存管理是交由编译器处理的,虽然程序员无需手动管理,但实际上也调用了new
和delete
,obj
对象只有申请,没有释放,obj2
是智能指针,其内存的生命周期由编译器进行管理,无需手动释放,在test
函数结束时会自动释放掉。
在main
函数中,pInt
的内存只有申请,没有释放,p
是智能指针,在main
函数结束时会自动释放。因此,该段代码有两处内存泄漏,分别为指针pInt
和obj
,我们运行该段代码:
[root@ck08 memleak]# g++ new.cpp -std=c++11 -g [root@ck08 memleak]# ./a.out Memory Not Freed: [0x7c5080] 12 bytes [0x7c50e0] 4 bytes
可以看到,确实打印出了两处内存泄漏,第一处是0x7c5080
,该地址是obj
的地址,第二处是0x7c50e0
,正是pInt
的地址。而指针p
即使是在main
函数结束时才被释放,但MemCheck
仍然能够感知到其内存被释放了。
本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对C/C++课程感兴趣的读者,可以点击链接,查看详细的服务:C/C++Linux服务器开发/高级架构师