发生内存泄漏主要是因为内存没有及时释放,即malloc后没有free。
实现一个检测出内存泄漏且能知道发生内存泄漏的代码行,首先要能检测出发生了内存泄漏,其次能定位到发生内存泄漏的地方。
一个方法是每当分配一个内存时就用一个文件来记录该地址,文件名为分配的地址,文件内容为builtin_return_address()的值,即调用函数的代码在代码段的位置。当释放某地址的时候再文件夹中找对应的文件名,若此文件存在则删除并释放地址,若不存在则是出现二次释放。当进程结束时,若还有剩余文件,则表示发生内存泄漏,通过文件内容可知发生内存泄漏的代码位置。
这需要重载malloc和free函数,实际分配和释放地址的函数使用malloc内部的_libc_malloc和_libc_free函数。
具体代码如下:
extern void *__libc_malloc(size_t size);
int enable_malloc_hook = 1;
extern void __libc_free(void* p);
int enable_free_hook = 1;
void *malloc(size_t size) {
if (enable_malloc_hook) {
enable_malloc_hook = 0;
void *p = __libc_malloc(size);
void *caller = __builtin_return_address(1); // 1
char buff[128] = {0};
sprintf(buff, "./mem/%p.mem", p);
FILE *fp = fopen(buff, "w");
fprintf(fp, "[+%p] --> addr:%p, size:%ldn", caller, p, size);
fflush(fp);
//fclose(fp); //free
enable_malloc_hook = 1;
return p;
} else {
return __libc_malloc(size);
}
return NULL;
}
void free(void *p) {
if (enable_free_hook) {
enable_free_hook = 0;
char buff[128] = {0};
sprintf(buff, "./mem/%p.mem", p);
if (unlink(buff) < 0) { // no exist
printf("double free: %pn", p);
}
__libc_free(p);
// rm -rf p.mem
enable_free_hook = 1;
} else {
__libc_free(p);
}
}
由于printf时内部会自动申请一款内存,所以用enable_malloc_hook来判断是否为malloc内部的printf调用的内存。否则会发生递归调用malloc
暑期编程PK赛 得CSDN机械键盘等精美礼品!


