Valgrind 是用于调试程序的工具套件,其中最有名的工具是Memcheck,它能够检测出C/C++ 中因为内存错误导致程序中断的问题。
一、引言
使用Valgrind 有两个必要条件:一安装了Valgrind;二需要在编译程序参数中加上 -g 选项;尽量不要使用 -O2 或者更高级别的代码优化,这样会导致Memcheck 误报未初始化的参数(uninitialised-value errors )。 调试方法非常简单,如果你的程序如下执行:
MyProg arg1 arg2 ...
那么这样使用如下命令:
valgrind --leak-check=yes MyProg arg1 arg2 ...
Memcheck 是默认工具(也可以用 –tool=memcheck 指定工具),–leak-check 选项打开了内存泄露检查工具。
二、常见选项
– -tool=<toolname> [default: memcheck]
用于选择工具,有Memcheck ,Cachegrind(模拟了CPU 中的cache L D,可分析cache 命中率) 等。
– -track-origins=yes
跟踪没有初始化参数
– -leak-check=yes
检查内存泄露
– -show-reachable=yes|No
当NO 的时候,只显示没有指针指向的内存,或者没有指向头部的指针
当YES 的时候,也有指向内存头部的指针,但内存没有释放。比如指针p malloc了一段地址,p 地址没有改变,并在程序结束时候没有释放。
常用YES。
三、常见错误或提示
Illegal read / Illegal write errors
Valgrind 认为你在不应该读写的地方读写了。比如:
Invalid read of size 4 at 0x40F6BBCC: (within /usr/lib/libpng.so.2.1.0.9) by 0x40F6B804: (within /usr/lib/libpng.so.2.1.0.9) by 0x40B07FF4: read_png_image__FP8QImageIO (kernel/qpngio.cpp:326) by 0x40AC751B: QImageIO::read() (kernel/qimage.cpp:3621) Address 0xBFFFF0E0 is not stack'd, malloc'd or free'd
在地址0xBFFFF0E0 的地方非法读了4 个Bytes 。
Use of uninitialised values
使用了未初始化的值
Illegal frees
非法释放。Memcheck 跟踪程序中分配和释放的所有内存,所以知道哪些内存释放是非法的。如下面的额错误就是因为同一段内存被释放了两次:
Invalid free() at 0x4004FFDF: free (vg_clientmalloc.c:577) by 0x80484C7: main (tests/doublefree.c:10) by 0x402A6E5E: __libc_start_main (libc-start.c:129) by 0x80483B1: (within tests/doublefree) Address 0x3807F7B4 is 0 bytes inside a block of size 177 free'd at 0x4004FFDF: free (vg_clientmalloc.c:577) by 0x80484C7: main (tests/doublefree.c:10) by 0x402A6E5E: __libc_start_main (libc-start.c:129) by 0x80483B1: (within tests/doublefree)
Passing system call parameters with inadequate read/write permissions
Memcheck 检查所有传入给系统调用的参数,下面的程序试图将一段malloc 的垃圾内存输出到屏幕:
#include#include int main( void ) { char* arr = malloc(10); (void) write( 1 /* stdout */, arr, 10 ); return 0; }
将会得到下面的信息:
Syscall param write(buf) contains uninitialised or unaddressable byte(s) at 0x4035E072: __libc_write by 0x402A6E5E: __libc_start_main (libc-start.c:129) by 0x80483B1: (within tests/badwrite) by??? Address 0x3807E6D0 is 0 bytes inside a block of size 10 alloc'd at 0x4004FEE6: malloc (ut_clientmalloc.c:539) by 0x80484A0: main (tests/badwrite.c:6) by 0x402A6E5E: __libc_start_main (libc-start.c:129) by 0x80483B1: (within tests/badwrite)
Overlapping source and destination blocks
C 中包含一些不安全的内存传输,比如 memcpy(), strcpy(), strncpy(), strcat(), strncat()。Memcheck 会检查目的地址和源地址是否重叠。
definitely lost, indirectly lost, possibly lost, still reachable and suppressed
definitely lost 表示一定有内存泄露
indirectly lost 表示你的程序在基于指针的结构发生内存泄露(比如树结构的root 是definitely lost, 孩子节点是indirectly lost)如果修复了definitely lost ,那么indirectly lost 也就解决了
possiblely lost 表示你的程序很有可能泄露内存,但存在指向这段内存中间的指针。–show-possible-lost=no 可以消除这些消息
still reachable 表示你的程序没有释放一些内存,但还是OK,因为有指向这些内存头的指针,系统会帮你释放–show-reachable=yes 消除这些消息
suppressed 不是很懂,因为是程序没有问题
四、参考资料
[1]. Valgrind FAQ http://valgrind.org/docs/manual/faq.html
[2]. Valgrind quick start http://valgrind.org/docs/manual/quick-start.html
[3]. Valgrind tutorial http://cs.ecs.baylor.edu/~donahoo/tools/valgrind/
[4]. User manual http://valgrind.org/docs/manual/manual.html
[5]. Valgrind 3.3.0 Manual http://www.network-theory.co.uk/valgrind/manual/
利器。
valgrind对内存bug很有帮助。