【C++】内存泄露检测

主要介绍利用library injection方法检测内存泄露.

library injection就是重载库里面对应的函数,让程序调用library里的函数,而不是调用库函数里的函数.

内存泄露主要是重载malloc和free函数,重载后,程序中调用malloc和free分配和释放内存时,就是利用自己编写的malloc和free函数.

1.library injection如何完成?

在linux环境下,可以利用LD_PRELOAD来指定编译好的重载库.

具体的方法如下:

1) g++ -shared -fPIC leakfinder.cpp -o leakfinder.so -ldl //编译得到重载malloc和free函数的动态库
2) export LD_PRELOAD=./leakfinder.so              //设定预先加载的动态库
3) ./c_example                           //执行例子程序
其中,重载malloc和free函数时,需要利用extern "C"来标识malloc和free函数.这是由于C++和C对函数的命名不致,C++中函数命名包含对应的参数,而C语言不包括.


2.重载的malloc和free函数如何实现,需要完成那些工作?  

1) 基本的内存分配和释放工作必须完成,可以调用系统本身的malloc和free函数完成.

利用void* dlsym(void* handle,const char* symbol)函数获取系统内的malloc和free函数指针,利用系统的malloc和free函数指针完成内存分配和释放的基本工作.

2) 保存内存分配的信息,便于检测最后是否存在内存泄露,利用vector来保存对应内存分配信息.

每次分配时,则添加一个记录信息到vector中,每次释放时,则从中搜寻对应的记录信息删除.

最后程序结果时,检测vector是否存在记录信息来判断是否发生内存泄露.

3) 内存分配信息的记录,包括分配的地址,利用函数调用顺序(便于内存泄露时,给出提示信息)

其中,在linux环境下,函数调用栈的信息通过backtrace和backtrace_symbols来获得.
4) 程序结束时,检测是否存在内存泄露,若存在,输出相应的信息.利用__attribute__(destructor)来指定程序结束后,执行的内存泄露统计信息.

static void compile_allocation() __attribute__((destructor));
5) 保存内存分配信息时,需要分配和释放内存,若不与外界的内存分配和释放进行区分,将会出现无限循环递归调用.

利用全局标记量来标识是从外部的调用,还是从内部的调用

6) 全局的标记量可能被多线程修改,导致出现线程不安全问题.因而需要利用互斥锁对内存信息保存进行控制.

参考文献:http://www.codeproject.com/Articles/393957/Cplusplus-Memory-Leak-Finder

原文地址:https://www.cnblogs.com/dwdxdy/p/2572869.html