Valgrind工具组提供了一套调试与分析错误的工具包,可以帮助你的程序工做的更加准确,更加快速。这些工具之中最有名的是Memcheck。它可以识别不少C或者C++程序中内存相关的错误,这些错误会致使程序崩溃或者出现不可预知的行为。html
接下来会以最短的篇幅告诉你如何使用Memcheck来识别你写的程序中的内存错误。你能够从用户手册中获取Memcheck的完整文档以及其余工具的使用说明。linux
在编译程序时开启-g
选项来引入调试信息,这样Memcheck的错误信息中可以准确的显示问题代码的序号。若是你可以容忍一些性能损失,请使用-O0
选项来编译程序.使用-O1
方式来编译程序错误信息可能会不许确,虽然大致而言在使用-O1
方式编译的程序上使用Memcheck没有问题,并且相比-O0
方式编译的程序而言性能大为提高.不推荐使用-O2
或者更高级别来编译程序,由于Memcheck偶尔会误报值未初始化的错误.数组
若是你的程序按照如下方式运行:函数
myprog arg1 arg2
工具
请使用下述命令来执行内存检查:性能
valgrind --leak-check=yes myprog arg1 arg2
指针
Memcheck是默认的工具,开启--leak-check
选项会启动内存泄露检查.调试
你的程序会比正常运行慢不少(大概20到30倍),而且会使用更多的内存.Memcheck会记录检测到的内存错误和内存泄露信息.code
这是咱们的用于示例的C程序代码,其文件名为a.c,这段代码中有一个内存错误和内存泄露问题.orm
#include <stdio.h> void f(){ int * x = malloc(10 * sizeof(int)); x[10] = 0; //problem 1: heap block overrun //problem 2: memory leak -- x not freed } int main(){ f(); return 0; }
下面是使用上述C代码生成程序的makefile文件.
example:example.o gcc -o example example.o example.o:a.c gcc -c -O0 -g -Wall a.c -o example.o .PHONY:clean clean: -rm -rf *.o example
使用下述命令检查程序中的内存错误:
valgrind --leak-check=yes ./example
大多数的错误信息和下面的一致,下面展现了内存越界的错误:
==5753== Invalid write of size 4 ==5753== at 0x40053B: f (a.c:5) ==5753== by 0x40054B: main (a.c:9) ==5753== Address 0x51fc068 is 0 bytes after a block of size 40 alloc'd ==5753== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5753== by 0x40052E: f (a.c:4) ==5753== by 0x40054B: main (a.c:9)
注意:
Invalid write
告诉你出现了哪种错误.由于内存泄露,程序向本不能访问的内存进行了写入操做.--num-callers
选项来扩充堆栈轨迹信息.推荐按照提示的顺序来修复错误.由于后面的错误可能由于前面的错误致使.不然你会以为Memcheck很差用.
内存泄露信息以下所示:
==5753== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==5753== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5753== by 0x40052E: f (a.c:4) ==5753== by 0x40054B: main (a.c:9)
堆栈追踪信息告诉你泄露的内存在哪里分配的.Memcheck不能告诉你为何内存会泄露.
有几种不一样的内存泄露方式,其中最重要的两种类别是:
若是你不理解错误信息,请查询用户手册中关于Memcheck错误信息的说明,其中举例说明了Memcheck产生的全部类型的错误信息.
Memcheck并不完美,它偶尔会误报,有些机制能够抑制这些误报.(请参考用户手册中的减小出错章节).然而,他在99%的状况下都不会出错,因此你须要谨慎地忽略它报告的错误信息.毕竟,你也不会忽略编译器的报警信息.抑制机制对于你不能修改的库代码也有用.默认的抑制会影响库代码中的内存错误.
Memcheck不可以侦测你程序中的全部内存错误.好比,他不能识别越界读,或者对分配到栈区的数组的越界写入.可是它可以识别能致使你程序崩溃的大多数错误.
尝试使你的程序更加清晰,这样Memcheck检测不出错误.当你达到这种状态,你会更容易发现对程序的哪些修改致使Memcheck报告了新的错误.数年的Memcheck使用经验说明,大型程序也可以使用Memcheck. 好比KDE,Firefox等.
请查询 Valgrind FAQ Valgrind User Manual.使用--tool选项可使用Valgrind中的其余工具.