Valgrind tool suite提供一些debugging和profiling工具,来让你的程序跑的更快,更正确。其中最流行的工具是memcheck,它能检测C/C++程序内存相关的错误,这些错误可能导致程序奔溃和不可预测的行为。
最好使用-g -O0选项编译程序。这样valgrind的报告更准确。
valgrind尽可能设计成 non-intrusive,它直接执行要调试的程序,不需要修改代码或重新编译。使用下面的方法开始调试程序:
1  | $ valgrind [valgrind-options] your-prog [your-prog-options] | 
最重要的选项是--tool,它指定要运行的valgrind工具。memcheck是默认的工具。程序运行在valgrind core提供的一个人造的(synthetic)CPU上。valgrind在执行指令前,将指令发送给tool,tool添加自己的指令,然后返还给core执行。memcheck工具检查每一条内存访问指令。因而可以获得非法的内存读写。大量的instrumentation code被添加,导致valgrind运行程序慢了10到50倍。
程序运行后,只有一个valgrind.bin进程,如下:
1 2 3 4  | $ valgrind ./a.out$ ps aux | grep a.outyuanjia+ 10846  112  1.2 120364 50596 pts/4    Sl+  07:37   0:06 /usr/bin/valgrind.bin ./a.out | 
top可以看到原本的两个线程:
1 2 3 4 5 6 7 8 9 10  | $ top -H -p `pidof valgrind.bin`top - 07:40:04 up 21 days,  5:59,  8 users,  load average: 0.90, 0.36, 0.14Threads:   2 total,   1 running,   1 sleeping,   0 stopped,   0 zombie%Cpu(s): 50.2 us,  0.2 sy,  0.0 ni, 49.0 id,  0.0 wa,  0.0 hi,  0.3 si,  0.3 stKiB Mem :  4039152 total,   287444 free,   495916 used,  3255792 buff/cacheKiB Swap:  4038652 total,  4034800 free,     3852 used.  3245980 avail Mem  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND10847 yuanjia+  20   0  120364  50596   4580 R 99.9  1.3   2:07.44 memcheck-amd64-10846 yuanjia+  20   0  120364  50596   4580 S  0.0  1.3   0:00.95 memcheck-amd64- | 
但是线程名被修改了。
可以给valgrind.bin发送信号,这个信号就好像发送给a.out一样。当然不可以捕获信号只能发送给valgrind.bin。
memcheck工具可以:
1 检查非法内存读写,如堆内存越界读写,栈顶非法写、访问释放后的内存。
2 使用未定义的变量。
3 不正确的堆内存释放,如重复释放,释放非堆内存等。
4 memcpy等函数src和dst重叠。
5 传一个非法的size给分配函数。
6 内存泄漏。
测试程序代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13  | #include <stdlib.h>void f(void){        int* x = malloc(10 * sizeof(int));        x[10] = 0; // problem 1: heap block overrun} // problem 2: memory leak -- x not freedint main(void){        f();        return 0;} | 
这段程序越界访问,并且没有释放分配的内存。
选项:
--undef-value-errors=no,不检查未定义值访问。
--leak-check=no,不检查内存泄漏。
当定位堆异常时,通常不要做这两个检查,否则打印输出很多。
使用valgrind调试:
$ valgrind --undef-value-errors=no --leak-check=no ./a.out
==11481== Memcheck, a memory error detector
==11481== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11481== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11481== Command: ./a.out
==11481==
==11481== Invalid write of size 4
==11481== at 0x108668: f (in /work/test/valgrid/a.out)
==11481== by 0x108679: main (in /work/test/valgrid/a.out)
==11481== Address 0x522d068 is 0 bytes after a block of size 40 alloc'd
==11481== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11481== by 0x10865B: f (in /work/test/valgrid/a.out)
==11481== by 0x108679: main (in /work/test/valgrid/a.out)
==11481==
==11481==
==11481== HEAP SUMMARY:
==11481== in use at exit: 40 bytes in 1 blocks
==11481== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==11481==
==11481== For a detailed leak analysis, rerun with: --leak-check=full
==11481==
上述日志详细打印了,非法访问了哪个内存。这个内存是在哪里分配的,
参考资料:
https://www.valgrind.org/docs/manual/valgrind_manual.pdf