TheValgrind Quick Start Guide
1. Introduction
The Valgrind tool suiteprovides a number of debugging and profiling tools that help you make yourprograms faster and more correct. The most popular of these tools is calledMemcheck. It can detect many memory-related errors that are common in C and C++programs and that can lead to crashes and unpredictable behaviour.
Valgrind包提供了一些能让你程序运行更快,更正确的调试和性能分析工具,最常用的是Memcheck,它能够检测出一些C/C++程序中的一些内存相关的错误,这些错误能够导致程序崩溃和不可预知行为。
The rest of this guide givesthe minimum information you need to start detecting memory errors in yourprogram with Memcheck. For full documentation of Memcheck and the other tools,please read the User Manual.
下面的部分提供了需要使用memecheck检查内存错误所需要的少量信息,Memcheck更全面的文档或其它工具可以参照用户指南。
2. Preparing your program
Compile your program with -g
to include debugginginformation so that Memcheck's error messages include exact line numbers. Using-O0
is also a good idea, if you can tolerate the slowdown. With-O1
line numbers in errormessages can be inaccurate, although generally speaking running Memcheck oncode compiled at -O1
works fairly well, and the speed improvement compared to running -O0
is quite significant. Useof-O2
and above is not recommended as Memcheck occasionally reportsuninitialised-value errors which don't really exist.
编译程序时带上-g参数,以便memcheck的错误信息中能够带上准确的行号,如果对性能无要求的话,可以考虑使用-o0参数,使用-o1参数提供的错误信息会不是那么准确,尽管官方认为Memcheck在-o1级别表现不错,特别是在性能方面相对-o0有较大改进,不推荐使用-o2来编译程序,因为会导致memcheck 上报一些根本不存在的类似初始化变量之类的错误。
3. Running your program under Memcheck
If you normally run yourprogram like this:
正常情况下以下面形式运行你的程序
myprog arg1 arg2
Use this command line:
使用valgrind以后
valgrind --leak-check=yes myprog arg1 arg2
Memcheck is the defaulttool. The --leak-check
optionturns on the detailed memory leak detector.
Memcheck是默认使用的工具,--leak-check
打开详细的内存泄露检测器
Your program will run muchslower (eg. 20 to 30 times) than normal, and use a lot more memory. Memcheckwill issue messages about memory errors and leaks that it detects.
此时程序运行非常慢(比正常情况下慢20-30倍),并且占用很多内存。运行完成以后,Memcheck将会发布内存错误和它检测到的内存泄露。
4. Interpreting Memcheck'soutput
Here's an example C program,in a file called a.c, with a memory error and a memory leak.
这是一个C程序的例子,在a.c文件中有一个内存错误和一个内存泄露。
#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 freed
int main(void)
{
f();
return 0;
}
Most error messages looklike the following, which describes problem 1, the heap block overrun:
错误如下所示,给出了上面所描述的问题1,内存越界
==19182== Invalid write of size 4
==19182== at 0x804838F: f (example.c:6)
==19182== by 0x80483AB: main (example.c:11)
==19182== Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (example.c:5)
==19182== by 0x80483AB: main (example.c:11)
Things to notice:
提示信息:
· Thereis a lot of information in each error message; read it carefully.
错误信息中信息量较大,仔细阅读
· The19182 is the process ID; it's usually unimportant.
19182是进程ID,一般不重要
· Thefirst line ("Invalid write...") tells you what kind of error it is.Here, the program wrote to some memory it should not have due to a heap blockoverrun.
第一行(无效写…)告诉你错误的类型,在这里是程序写了一段不该写的堆内存,即越界写。
· Belowthe first line is a stack trace telling you where the problem occurred. Stacktraces can get quite large, and be confusing, especially if you are using theC++ STL. Reading them from the bottom up can help. If the stack trace is notbig enough, use the --num-callers
option to make it bigger.
接下来一行是堆栈跟踪信息,告诉你问题出在那了,堆栈跟踪信息可以打印很多,特别是使用c++STL 的时候,非常不好看,一般从下往上看,如果栈信息不够,使用--num-callers
参数可以打印更多。
· Thecode addresses (eg. 0x804838F) are usually unimportant, but occasionallycrucial for tracking down weirder bugs.
代码的地址不是重要信息,但是在跟踪一些疑难BUG时还是相关重要的。
· Someerror messages have a second component which describes the memory address involved.This one shows that the written memory is just past the end of a blockallocated with malloc() on line 5 of example.c.
一些错误信息带了内存地址信息,这个就显示了写内存时写到了malloc分配的内存后面在example.c的第五行。
It's worth fixing errors inthe order they are reported, as later errors can be caused by earlier errors.Failing to do this is a common cause of difficulty with Memcheck.
沿着Memcheck上报的顺序解决问题,因为后面的错误可能是由前面的错误引起的。不这样处理是很难使用memcheck 的通用原因。
Memory leak messages looklike this:
内存泄露信息看起来和下面类似:
==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (a.c:5)
==19182== by 0x80483AB: main (a.c:11)
The stack trace tells youwhere the leaked memory was allocated. Memcheck cannot tell you why the memoryleaked, unfortunately. (Ignore the "vg_replace_malloc.c", that's animplementation detail.)
堆栈跟踪告诉你泄露的内存是在那分配的,memcheck 没有办法告诉你内存为什么泄露。
There are several kinds ofleaks; the two most important categories are:
有多种类型的内存泄露,下面是两类最重要:
· "definitelylost": your program is leaking memory -- fix it!
确定泄露:你的程序在泄露内存-修复它
· "probablylost": your program is leaking memory, unless you're doing funny thingswith pointers (such as moving them to point to the middle of a heap block).
可能的内存泄露,程序在泄露内存,除非在做一些可笑的事情,比如把指针移到堆的中间。
Memcheck also reports usesof uninitialised values, most commonly with the message "Conditional jumpor move depends on uninitialised value(s)". It can be difficult todetermine the root cause of these errors. Try using the --track-origins=yes
to get extra information. This makes Memcheck run slower, but the extrainformation you get often saves a lot of time figuring out where theuninitialised values are coming from.
Memcheck也会上报一些未初始化的变紧,通常会提示条件跳转或移动依赖未初始化的数据,通常很难确定这些错误的根本原因,尝试使用--track-origins=yes
可以获得更多信息,这个参数会拿memcheck运行更加慢,但是更详细的信息能节省查询未初始化变量来源的时间。
If you don't understand anerror message, please consultExplanationof error messages from Memcheckin the ValgrindUser Manualwhichhas examples of all the error messages Memcheck produces.
如果不理解错误信息,可以咨询valgrind 用户指南中的“memcheck错误信息解释”,这里面有一些相关错误信息的例子。
5. Caveats
Memcheck is not perfect; itoccasionally produces false positives, and there are mechanisms for suppressingthese (see Suppressing errorsin the ValgrindUser Manual).However, it is typically right 99% of the time, so you should be wary ofignoring its error messages. After all, you wouldn't ignore warning messagesproduced by a compiler, right? The suppression mechanism is also useful ifMemcheck is reporting errors in library code that you cannot change. Thedefault suppression set hides a lot of these, but you may come across more.
Memcheck并不完美,也会偶尔产生虚假错误信息当然也有一些机制来抑制这种情况,但是它能做取99%的正确,所以还是得关注它的错误信息,另外,不要忽略编译器的警告信息,当报告的错误来源于库代码时抑制也还是有用的,默认的抑制集合隐藏了很多类类似错误,但是你可能会遇到更多。
Memcheck cannot detect everymemory error your program has. For example, it can't detect out-of-range readsor writes to arrays that are allocated statically or on the stack. But itshould detect many errors that could crash your program (eg. cause asegmentation fault).
Memcheck不能检测出所有的内存错误,例如,它不能检测出越界读操作也不能检测出在一个在栈上已分配的数据的写操作,但是还是能检测出很多让你程序崩溃的错误。