内存泄漏分析工具--Valgrind


0 快速入门指南

0.1 简介

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。
Valgrind提供了许多调试和分析工具,这些工具中最受欢迎的称为 Memcheck。它可以检测 C 和 C++ 程序中常见的许多与内存相关的错误,这些错误可能导致崩溃和不可预知的行为。

0.1.1 Linux安装valgrind

  1. 下载valgrind安装包
    下载地址
  2. 安装
tar -x -j -f valgrind-3.18.1.tar.bz2
cd valgrind-3.18.1/
./configure
make
make install

可参考README文件中的安装步骤。

  1. 测试valgrind是否工作
valgrind ls -l

0.2 准备你的程序

编译你的程序,加-g以包含调试信息,以便Memcheck的错误消息包含准确的行号。

0.3 在Memcheck下运行你的程序

如果你通常像这样运行程序:

myprog arg1 arg2

使用这个命令:

valgrind --leak-check=yes myprog arg1 arg2

Memcheck是默认工具。该--leak-check选项打开内存泄漏检测器。
你的程序将比正常运行慢得多,并使用更多内存。Memcheck将发布它检测到的内存错误和内存泄漏的信息。

0.4 解释Memcheck的输出

这是一个示例C程序,在一个名为a.c的文件中,存在内存错误和内存泄漏。

#include 

void f(void)
{
     int* x = malloc(10 * sizeof(int));
     x[10] = 0;        // problem 1: heap block overrun
}                    // problem 2: memory leak -- x not freed

int main(void)
{
     f();
     return 0;
}

检测a.c,输出信息如下:

==2565877== Memcheck, a memory error detector
==2565877== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2565877== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==2565877== Command: ./a.out
==2565877== 
==2565877== Invalid write of size 4
==2565877==    at 0x4005B4: f (a.c:5)
==2565877==    by 0x4005C5: main (a.c:10)
==2565877==  Address 0x520b068 is 0 bytes after a block of size 40 alloc'd
==2565877==    at 0x4C36001: malloc (vg_replace_malloc.c:381)
==2565877==    by 0x4005A7: f (a.c:4)
==2565877==    by 0x4005C5: main (a.c:10)
==2565877== 
==2565877== 
==2565877== HEAP SUMMARY:
==2565877==     in use at exit: 40 bytes in 1 blocks
==2565877==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==2565877== 
==2565877== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2565877==    at 0x4C36001: malloc (vg_replace_malloc.c:381)
==2565877==    by 0x4005A7: f (a.c:4)
==2565877==    by 0x4005C5: main (a.c:10)
==2565877== 
==2565877== LEAK SUMMARY:
==2565877==    definitely lost: 40 bytes in 1 blocks
==2565877==    indirectly lost: 0 bytes in 0 blocks
==2565877==      possibly lost: 0 bytes in 0 blocks
==2565877==    still reachable: 0 bytes in 0 blocks
==2565877==         suppressed: 0 bytes in 0 blocks
==2565877== 
==2565877== For lists of detected and suppressed errors, rerun with: -s
==2565877== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

根据上述信息得,有两处错误:

  1. Invalid write of size 4。根据at 0x4005B4: f (a.c:5)可知是a.c的第5行出错。
  2. 40 bytes in 1 blocks are definitely lost in loss record 1 of 1。根据at 0x4C36001: malloc (vg_replace_malloc.c:381)可知已泄露内存的分配位置(已泄漏的内存是在哪里被分配的)。

2565877是进程ID,通常不重要。

0.5 注意事项

Memcheck并不完美,它偶尔会产生误报,并且有抑制这些错误的机制。但是,它通常在99%的情况下都是正确的。
Memcheck 无法检测您的程序存在的每个内存错误。例如,它无法检测对静态分配或堆栈上的数组的超出范围的读取或写入。

1