Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186425
  • 博文数量: 37
  • 博客积分: 171
  • 博客等级: 入伍新兵
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-13 22:54
个人简介

寻找方向程序猿、攻城狮

文章存档

2023年(1)

2022年(4)

2019年(1)

2018年(1)

2017年(1)

2015年(2)

2014年(19)

2013年(2)

2012年(1)

2011年(5)

分类: LINUX

2013-10-10 15:23:21

Release 3.8.0 10 August 2012
Copyright © 2000-2012 Valgrind Developers

1. 介绍

valgrind工具套装提供了一系列的调试和剖析工具,开发人员可以利用这些工具使得程序更加快速,或者纠正程序的错误。这么多工具里面最受欢迎的是Memcheck。它能够探测很多内存相关的错误,这些错误通常在C和C++程序中,能够导致崩溃和不可预期的行为。这个指南的其余部分给出了你在你的程序中使用Memcheck来探测内存错误的最少的信息。如果需要关于Memcheck和其他工具的完整的信息,请阅读用户手册。

 2. 准备好你的程序

注意,编译你的程序的时候需要加上“-g”选项,使得程序包含debugging信息,Memcheck的错误消息才可以包含准确的行数。如果你能忍受你的程序运行速度变得更慢,那么使用-O0选项也是一个好主意。尽管我们通常说程序编译的时候使用-O1选项,使用Memcheck也能正常工作,并且运行速度相对于使用-O0选项来说快的多,但是使用-O1选项,错误消息的行号可能是错的。不推荐使用-O2或更高级别的选项,因为如果使用,Memcheck会突然报“值没有初始化”的错误,但实际上这是不存在的。

3. 在Memcheck上运行你的程序

如果你一般情况下使用如下命令运行你的程序:
myprog arg1 arg2
那么使用如下命令让valgrind检测你的程序:
valgrind --leak-check=yes myprog arg1 arg2

Memcheck是默认使用的工具,--leak-check选项开启详细的内存泄露探测。
你的程序运行速度将比正常情况低20到30倍,并且使用更多内存。Memcheck将显示它探测到的内存错误。

4. 解释Memcheck的输出

下面是一个示例c语言,在文件a.c中,包含了一个内存错误和一个内存泄漏。
1
#include
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)
注意:
? 每一个错误消息都有很多信息,请仔细阅读。
? 19182是进程ID,通常不是重要的。
? 第一行 ("Invalid write...") 说明错误类型。 这儿,程序越界访问了,它本来不应该越界访问堆块。
? 第二行开始是一个stack trace,说明问题发生在哪儿。stack traces可能变得非常大,以及混乱,特别是你在使用C++ STL的时候。从下到上阅读stack trace是有帮助的。如果stack trace不够大,那么使用--num-callers选项使得它足够大。
? 代码地址(譬如0x804838F)通常是不重要的,但有时用来跟踪一些很奇怪的Bug又是很重要的。
? Some error 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 block allocated with malloc() on line 5 of example.c.

最好按它们报告的顺序修复错误,因为后面的Bug可能是由前面的Bug引起的。没有这么做,通常导致Memcheck存在问题(Failing to do this is a common cause of difficulty with 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)
这个stack trace告诉你,泄漏的内存是在哪儿分配的。但是不幸的是Memcheck不能告诉你内存为什么泄漏(忽略"vg_replace_malloc.c",这是一个实现细节)。
有几种类型的泄漏,最重要的两个类别是:
? "definitely lost": 你的程序正在泄漏内存--修复它!
? "probably lost": 你的程序正在泄漏内存,除非你正在使用指针在做某些事情(譬如将指针移到堆块的中间)。
Memcheck也报告没有初始化值的使用,大部分使用这样的消息:“Conditional jump or move
depends on uninitialised value(s)"。确定导致这些错误的根本原因是困难的。使用--track-origins=yes选项获取额外的信息。这会使得Memcheck运行的更慢,但是你所获取到的额外的信息会使得你节省很多时间去确定未初始化值来自哪里。如果你不理解一个错误消息,请查阅Valgrind用户手册中Memcheck的错误消息,手册中包含了Memcheck产生的所有错误消息的示例。

5. 警告

Memcheck是不完美的;它偶尔产生错误的正数,但有几种机制来压制这些错误(查看Valgrind用户手册中的Suppressing errors)。然而,一般来说99%是对的,所以你可以放心。毕竟,你不应该忽略一个编译器产生的警告信息,不是吗?suppression机制是非常有用的,譬如Memcheck正在报告你所不能改动的类库的错误的时候,可以让Memcheck不报告这类错误。缺省的suppression设置隐藏了大量的这样的信息,但是你可能会遇到更多。
Memcheck不能够探测你的程序中所有的每一个内存错误。例如,他不能够探测静态分配的或在stack内的数组的越界访问。但是,它应该可以探测到可能导致你的程序崩溃的很多错误(譬如,导致段错误)。尝试使你的程序干净,以致Memcheck没有报告错误。一旦你达到这个状态,那么很容易看到由于程序的改动而导致Memcheck报告新的错误。
从这几年使用Memcheck的经验看来,Memcheck对于大型的程序也有很大的用户,可以使这些程序更干净。例如,KDE的大部分,OpenOffice.org和Firefox都使用Memcheck,还有很多其他的程序。

6. 更多信息

请阅读Valgrind FAQ和Valgrind用户手册,它们有更多的信息。注意Valgrind的其他工具可以使用--tool选项调用。

阅读(1709) | 评论(0) | 转发(0) |
0

上一篇:算法定义

下一篇:bios中断大全

给主人留下些什么吧!~~