1、函数重载的方法
2、具体实现
代码工程中,申请和释放内存是通过malloc和free实现的。接下来的工作就是对malloc和free两个函数实现重载。在malloc重载函数中创建一个文件,文件名由malloc返回的地址命名,文件中保存调用malloc重载函数的地址。在free重载函数中删除以释放地址命名的文件。运行一段时间后,查看剩余的文件,剩余文件就是可能出现内存泄漏的地址,通过保存在文件中的数据确认调用malloc的地方。
2.1、malloc函数的重载
void *malloc(size_t size)
{
void *p = NULL;
void *caller = NULL;
char buf[MEM_CONTENT_LENGTH] = {0x00};
FILE *fp = NULL;
Dl_info info;
if (malloc_stub_enable) { //malloc_stub_enable解决嵌套问题,因为printf也会调用malloc
malloc_stub_enable = 0;
p = malloc_f(size);
//获取调用malloc函数那一层的地址,由编译器决定
caller = __builtin_return_address(0);
memset(&info, 0x00, sizeof(Dl_info));
(void)dladdr((void*)caller, &info);
sprintf(buf, "./tmp/%p.mem", p);
//以函数返回值命名文件
fp = fopen(buf, "w");
//存放调用malloc函数的地址
fprintf(fp, "[+%p]malloc --> caller: %s, addr: %p, size: %lu\n", caller, info.dli_sname, p, size);
fflush(fp);
malloc_stub_enable = 1;
return p;
} else {
return malloc_f(size);
}
}
2.2、free函数的重载
void free(void *p)
{
char buf[MEM_CONTENT_LENGTH] = {0x00};
if (free_stub_enable) {
free_stub_enable = 0;
sprintf(buf, "./tmp/%p.mem", p);
//unlink删除文件
if (unlink(buf) < 0) {
printf("double free: %p\n", p);
}
free_stub_enable = 1;
}
free_f(p);
}
2.3、运行一段时间后获取数据文件
2.3.1、工程本身函数出现的内存泄漏
该地址是程序运行时候的地址,需要减去程序本身的基地址。基地址通过cat /proc/$pid/maps查看
解析地址:addr2line -fe ./malloc_main -a 0xd0a
2.3.2、动态库中出现的内存泄漏
获取动态库加载时候的基地址
2.3.3、静态库中出现的内存泄漏。静态库的函数已经编译到调用的函数中,不存在于静态库中
3、测试demo源码