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服务器开发/高级架构师