一. 简介
在 Linux 环境下进行 C/C++ 开发过程中,经常会使用 malloc/calloc() 函数分配堆空间,常常因为疏忽,忘记释放堆内存。从而导致内存泄露问题。
当发生肉眼可见大量的内存泄露时,可以使用 shell 命令来确认是否存在泄露。
但是,当每次程序只是发生几个字节的内存泄露时,shell 命令可能无法察觉到内存泄露问题。
这里介绍一种监测代码发生几个字节内存泄露的方法。
二. Linux下发生几个字节内存泄露排查方法一
1. 检测方法实现思路:
首先,在代码当前目录创建一个目录,存放调试log信息。
其次,自定义堆空间申请与释放的函数,即对堆空间申请/释放函数进行封装。在自定义的堆申请函数中,创建一个以堆地址命令的文件。
其次,在自定义的堆释放函数中,删除文件。
最后,将这部分监测代码用来测试代码中是否存在内存泄露。
注意: 这种方法只适用于单个 C/C++ 源文件,即对一个 C 文件中内存泄露问题的排查。
2. 方法使用实例:
下面介绍具体的监测方法。在源码当前目录创建一个目录文件,下面创建了一个 debug目录。C 代码实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define FILE_CONTENTS "./debug"
char file_name[256] = {0};
void* check_malloc(size_t size, const char* file, int line)
{
void* p = malloc(size);
sprintf(file_name, "%s/%p.mem", FILE_CONTENTS, p);
FILE* fp = fopen(file_name, "w");
fprintf(fp, "[+%s line: %d]--->addr: %p, size: %ld\n", file, line, p, size);
fflush(fp);
fclose(fp);
return p;
}
void check_free(void* p, const char* file, int line)
{
sprintf(file_name, "%s/%p.mem", FILE_CONTENTS, p);
if(unlink(file_name) < 0) //file no exist
{
printf("double free: %p\n", p);
return;
}
free(p);
}
#define malloc(size) check_malloc(size, __FILE__, __LINE__)
#define free(p) check_free(p, __FILE__, __LINE__)
int main(void)
{
char* p1 = (char*)malloc(20);
char* p2 = (char*)malloc(30);
free(p2);
p2 = NULL;
return 0;
}
使用上面代码即可对单个源码文件中代码进行内存泄露的排查。如下演示一下对下面一段代码的排查。
操作如下:
首先,在当前目录下,创建一个存放调试 log 信息的目录文件 debug。
其次,将第一段代码添加到待调试代码中。进行编译,即输入 gcc -g main.c -o main.out 命令。
最后,当存在内存泄露时会在 debug 文件中生成 相关文件。
如下所示:在 debug 目录下生成了 调试 Log 信息。可以看出,在代码 main.c 的 38 行出现了内存泄露问题。如下: