Valgrind Tutorial

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 Tutorial》上有1条评论

回复 fumin 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据