一.  简介

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 行出现了内存泄露问题。如下:

Linuxjava内存溢出分析工具 linux内存溢出排查_内存泄露