valgrind官方手册翻译(一)_20151128

Quick Start Guide

快速上手

快速上手列表

1、简介

2、你的程序应当作的准备

3、使用memcheck检测你的程序

4、memcheck输出含义

5、注意事项

6、更多信息

简介

Valgrind系列工具是提供一系列可以使你的程序运行更快更稳定调试、监测工具组。这里面最常用的便是memcheck工具,它能够检测出C和C++程序中的多种致命的内存问题。

下面的使用说明主要是教你快速上手memcheck工具,如何用它来检测你的程序中的内存问题。若想了解memcheck或者其他工具完整的说明文档,请参照用户手册(User Manual)。

你的程序应当作的准备

1、编译程序的时候需要添加-g选项,这样memcheck的报错信息便可以通过调试信息包括具体出错代码的行数。

2、如果你在调试程序时不介意程序的运行速度,那么建议你选择-O0的编译优化选项。如果选择-O1编译优化级别,虽然,memcheck大多数情况下依然是正常工作,报错信息也基本准确,但是错误代码行数有可时会不准确。

3、不推荐使用-O2以上的编译优化级别,memcheck会误报未初始化变量错误。

使用memcheck检测你的程序

若你的程序运行命令如下

myprog arg1 arg2

那么使用如下的格式便可以使用memcheck检查你的程序中的内存问题

valgrind --leak-check=yes myprog arg1 arg2

memcheck是valgrind的默认工具,”–leak-check”选项用于检测内存泄漏。

使用valgrind之后,你的程序运行相较于普通时候会慢20~30倍,并且会占用更多的内存。作为补偿,memcheck工具会详细地打印出它所监测到的内存问题和内存泄漏。

memcheck输出含义

下面的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;
}

大多数的错误信息会像下面这样(下面的错误信息示例是上面示例代码的错误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)

注意:

1、每条错误消息都有详细的错误描述信息,记得仔细阅读

2、19182是进程ID

3、第一行(Invalid write…)是说明这是哪种错误。这里的意思是说这里有违法写操作,会导致程序出问题

4、第一行下面的则是追踪栈(第二行到第三行),它会告诉你错误发生在哪里。有的时候,程序追踪栈是会特别大,或者是难以理解,特别是你使用c++ STL库的时候。建议你自下而上地阅读函数追踪栈。如果由于函数追踪栈特别大,导致打印出来的函数追踪栈并不完全,则建议你使用’–num-callers’选项提升打印栈大小。

5、代码地址(例如:0x804838F)通常来说并不重要,但是有时候通过查看代码地址查出某些怪异的bug,例如代码地址若为0x00000000则显然是有问题的。

6、有些错误消息会有额外的信息(第4~第7行)来描述错误相关的内存地址信息。这条信息是说写的内存位置超过了malloc申请的地址空间,该错误是在程序example.c的第五行。

修复错误最好按照memcheck报告的错误顺序来进行修复,根据经验往往很多后面的错误是由前面的错误导致的。如果不按照这么做的话,通常会带来许多不必要的麻烦。

内存泄漏的消息示例如下

  ==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)

追踪栈将会告诉你泄漏的内存是在哪里申请的。不幸的是,memcheck并不能告诉你因为什么操作导致内存泄漏。(请无视’vg_replace_malloc.c’,这是一个代码实现细节)

内存泄漏分很多种,两种最常见的内存泄漏是:

1、’definitely lost’直接泄漏:你的程序确实发生了内存泄漏,修复它!

2、’probably lost’可能泄漏:你的程序有可能要发生内存泄漏,除非你做一些搞笑的事情(比如:把指向一块内存地址头的指针,而且指向这块内存地址头的指针只有一个,然后你把该指针指向该内存的内部的位置,这样便会发生内存泄漏,因为通常来说你把指针指向别处,那么程序很难指导申请的该处内存的头部是哪里,除非人为规定,但是依然很容易出现各种错误)

memcheck也会报告使用未初始化变量错误,通常报错名称为’Conditional jump or move depend on uninitialised value(s)’。通常很难判断这些错误的根因是什么,这时候你可以使用’–track-origins=yes’选项获得额外的信息来判断原因。虽然该选项会使得memcheck运行得更慢,但是实际上所获得的额外信息大大节省了你在寻找和考虑这个问题的原因是什么的时间。

如果你不懂memcheck所报出的错误,请查询memcheck用户手册,那里很详细。

注意事项

memcheck也并不完美;它偶尔也会出现误报,不过有抑制这种误报的方法(具体抑制方法请参看《用户手册》)。然而,memcheck在99%的情况下都是正确的,所以你最好不要因为你认为有可能memcheck报得错误是错的就不管该错误信息。毕竟,你并不会忽略编译器报的警告错误,对吧!memcheck的抑制机制也对它报出系统库函数中的错误有用,因为你不能修改系统库函数,所以只能避开它。memcheck的默认设置已经过滤掉很多误报,但是并不代表你就不会遇到问题。

memcheck并不能检测出你程序中的每一个内存错误。例如,它不能检测出来越界读操作、不能检测出静态申请的内存或静态栈上进行写操作。但是它肯定能够检测出很多能让你程序崩溃的错误(例如,segmentation fault段错误)

尽量让你的程序’clean’这样memcheck便能更准确的报出错误。一旦你能够做到这样,那么你将会更容易检测出新加入的代码中是哪里出了问题导致memcheck报出新的错误。从过去几年使用memcheck工具的经验中,大型代码通过memcheck检查、清理,也是能够做到memcheck零报错。比如,KDE的很大一部分,OpenOffice.org和Firefox使用memcheck检查过后,是没有或者基本没有memcheck报出的错误的。

更多信息

FAQ和用户手册

你可能感兴趣的:(valgrind)