Valgrind检查内存泄露
包括工具
Memcheck
。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。- Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
- Cachegrind。它主要用来检查程序中缓存使用出现的问题。
- Helgrind。它主要用来检查多线程程序中出现的竞争问题。
- Massif。它主要用来检查程序中堆栈使用中出现的问题。
- Extension。可以利用core提供的功能,自己编写特定的内存调试工具。
显然,第一个是重中之重.
使用
准备程序
建议加上-g
的参数,编译优化选项请选择O0,虽然这会降低程序的执行效率。
示例代码如下:test.c
#include <stdlib.h>
void fun()
{
int *p = (int *)malloc(10*sizeof(int));
p[10] = 0;
}
int main()
{
fun();
return 0;
}
运行可执行程序
调用Valgrind的通用格式是:
valgrind [valgrind-options] your-prog [your-prog-options] 在本机编译过后,执行:
valgrind ./test
得到的命令结果如下:
==29859== Memcheck, a memory error detector
==29859== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==29859== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==29859== Command: ./test
==29859==
==29859== Invalid write of size 4
==29859== at 0x8048438: fun (in /home/xxx/test/test)
==29859== by 0x804844A: main (in /home/xxx/test/test)
==29859== Address 0x4204050 is 0 bytes after a block of size 40 alloc'd
==29859== at 0x40299D8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==29859== by 0x804842E: fun (in /home/xxx/test/test)
==29859== by 0x804844A: main (in /home/xxx/test/test)
==29859==
==29859==
==29859== HEAP SUMMARY:
==29859== in use at exit: 40 bytes in 1 blocks
==29859== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==29859==
==29859== LEAK SUMMARY:
==29859== definitely lost: 40 bytes in 1 blocks
==29859== indirectly lost: 0 bytes in 0 blocks
==29859== possibly lost: 0 bytes in 0 blocks
==29859== still reachable: 0 bytes in 0 blocks
==29859== suppressed: 0 bytes in 0 blocks
==29859== Rerun with --leak-check=full to see details of leaked memory
==29859==
==29859== For counts of detected and suppressed errors, rerun with: -v
==29859== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
结果分析
- 左边显示类似行号的数字(29859)表示的是 Process ID。
- 最上面表示的是 valgrind 的版本信息。
- 中间表示 valgrind 通过运行被测试程序,发现的内存问题。通过阅读这些信息,可以发现:这是一个对内存的非法写操作,非法写操作的内存是4 bytes。发生错误时的函数堆栈,以及具体的源代码行号。非法写操作的具体地址空间。
- 最下面是对发现的内存问题和内存泄露问题的总结。内存泄露的大小(40 bytes)也能够被检测出来。
- 示例程序显然有两个问题,一是fun函数中动态申请的堆内存没有释放;二是对堆内存的访问越界。这两个问题均被valgrind发现。