最近空闲时间比较多,于是,决定自行研究点东西。话不多说,这个系列是翻译valgrind官网的文档手册,第一次做这样的事情,尽量吧~
先介绍下valgrind是什么东东:
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。Valgrind这个名字取自北欧神话中英灵殿的入口(摘自wiki百科)
那么下面就开始吧。
valgrind快速入门指南
1、介绍:
这个valgrind工具系列提供若干调试和分析工具以帮助你的程序更快、更健壮。这其中的佼佼者就是memcheck了,它能检测到许多内存相关的错误,这些错误存在于你写的c/c++程序当中,并且这些错误可能导致程序崩溃或者出现一些不可预知的行为。
本指引提供让你运用memcheck上手去检测你编写的程序的内存错误的最少的信息,如果要了解更多关于Memcheck的文档信息或者其它工具,请参考官网的user manual。
2、准备你的程序:
让你的程序带有-g的编译选项,这样可以让memcheck工具能精准的标识行号等信息。如果你能容忍程序稍微慢点,加上-00就更好了。如果是-01选项,那么行号的错误信息可能不是很准确,虽然整体来说memcheck工具在这个编译选项下也工作的很好并且相比-00速度更快。-02的编译选项就不推荐了,因为这样会容易导致memcheck误报错。
3、让你的程序在memcheck下运行:
如果你是这样运行你的程序的:
myprog arg1 arg2
那么可以运行这个命令行
valgrind --leak-check=yes myprog arg1 arg2
memchekc是默认的工具,--leak-chekc选项是打开具体的内存泄漏探测器。
运行memcheck之后,你的程序会比原来的慢20-30倍,并且占用更多内存,memcheck会对探测到的内存错误或者泄漏进行消息显示。
4、打断memcheck的输出:
这里有一个示例程序叫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; }
多数错误信息如下所示,用来描述problem 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)
这里有大量的错误信息,需要仔细读。
19182是进程id,通常这是没有用的。
第一行的 错误提示(invalid write)告诉你这是什么样的错误,这里是指程序写了堆中的越界非法内存。
第一行以下的是这个错误发生的一些堆栈跟踪信息。这些堆栈跟踪可能很大,可能让你迷惑,尤其是你运用了c++ STL之后。
代码地址比如 0x804838F通常是没用的,但是有时对一些奇怪的错误又是关键性的信息。
但是,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不能告诉你为什么会造成内存泄漏。这里可能有几种内存泄漏,最重要的两种如下所示:
definitely lost:那么这表明你的程序存在内存泄漏,修复它
probably lost:那么这表明你的程序存在内存泄漏,除非是你正在使用指针(比如用指针向堆中内存move数据)
memchekc同样会报对未初始化变量的使用,一般会显示这样的信息“"Conditional jump or move depends on uninitialised value(s)"”,这很难定位错误根源,可以尝试使用--track-origins=yes来得到额外的信息,不过这会导致程序运行的更慢,不过这些额外的信息能帮助你比较快速定位的未初试化变量的来源。
5、警告:
memcheck不是完美的,它偶尔会报错误的错,不过这里有机制压抑它,详细见user manual。
不过,它能保证99%的正确率,所以你应该警惕它的报错信息,毕竟,就像你不会忽略编译器的错误信息,对吗?
memchekc不能侦探到程序的每个内存错误,举例说明,它不能检测到越界读写栈中静态分配的数组的错误,但是它还是可以帮助你找到很多可能导致你程序崩溃的内存错误的
努力尝试使你的程序很干净,让memcheck都不会报任何错误信息。一旦你达到这个状态,当你的程序发生变更 ,你就很容易知道memcheck报的新错误了。几年以上的memcheck使用经验可以让你,即使很大的程序都能做到memcheck 不报任何错误,也就是memcheck-clean.这里有不少这样的例子,比如BSD/Firefox/OpenOffice.org,这些项目都是memcheck-clean.
6、更多信息:
更多信息请咨询FAQ或者浏览User manual。链接为:http://valgrind.org/docs/manual/manual.html,英文版,有时间继续翻译。