Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,是公认的最接近Purify的产品,它包含一个内核——一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务——调试,分析,或测试等。Valgrind可以检测内存泄漏和内存越界,还可以分析cache的使用等,灵活轻巧而又强大。

1.Valgrind概观

Valgrind的最新版是3.2.3,该版本包含下列工具:

    1)memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。

    2)callgrind:检测程序代码覆盖,以及分析程序性能。

    3)cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。

    4)helgrind:用于检查多线程程序的竞态条件。

    5)massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

    6)lackey:

    7)nulgrind:

2.Valgrind工具详解

2.1 Memcheck

最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc、free、new、delete的调用都会被捕获。所以,它能检测以下问题:

1)对未初始化内存的使用;

2)读/写释放后的内存块;

3)读/写超出malloc分配的内存块;

4)读/写不适当的栈中内存块;

5)内存泄漏,指向一块内存的指针永远丢失;

6)不正确的malloc/free或new/delete匹配;

7)memcpy()相关函数中的dst和src指针重叠。

  这些问题往往是C/C++程序员最头疼的问题,Memcheck能在这里帮上大忙。

2.2 Callgrind

和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。

说明:这个工具我也没有用会,网上基本没有找到有指导性的文档,暂时留在后面慢慢研究吧。

2.3 Cachegrind

Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。作一下广告:valgrind自身利用该工具在过去几个月内使性能提高了25%-30%。据早先报道,kde的开发team也对valgrind在提高kde性能方面的帮助表示感谢。

2.4 Helgrind

它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验阶段。

2.5 Massif

堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。Massif对内存的分配和释放做profile。程序开发者通过它可以深入了解程序的内存使用行为,从而对内存使用进行优化。这个功能对C++尤其有用,因为C++有很多隐藏的内存分配和释放。

  此外,lackey和nulgrind也会提供。Lackey是小型工具,很少用到;Nulgrind只是为开发者展示如何创建一个工具。我们就不做介绍了。

3.使用Valgrind

Valgrind使用起来非常简单,你甚至不需要重新编译你的程序就可以用它。当然如果要达到最好的效果,获得最准确的信息,还是需要按要求重新编译一下的。比如在使用memcheck的时候,最好关闭优化选项。

valgrind命令的格式如下:

valgrind [valgrind-options] your-prog [your-prog options]

一些常用的选项如下:

选项

作用

-h --help

显示帮助信息。

--version

显示valgrind内核的版本,每个工具都有各自的版本。

-q --quiet

安静地运行,只打印错误信息。

-v --verbose

打印更详细的信息。

--tool=<toolname> [default: memcheck]

最常用的选项。运行valgrind中名为toolname的工具。如果省略工具名,默认运行memcheck。

--db-attach=<yes|no> [default: no]

绑定到调试器上,便于调试错误。

3.1 检测内存泄漏

示例代码如下:

 #include <stdlib.h>

 #include <stdio.h>

 int main(void)

 {

        char *ptr;

        ptr = (char *)malloc();

        return ;

 }

  保存为memleak.c并编译,然后用valgrind检测。

 $ gcc -o memleak memleak.c

  (valgrind和purify最大的不同在于:valgrind只接管程序执行的过程,编译时不需要valgrind干预,而purify会干预程序编译过程)

 $ valgrind --tool=memcheck ./memleak

  我们得到如下错误信息:

 [konten@tencent test_valgrind]$ valgrind ./memleak

 ==29646== Memcheck, a memory error detector.

 ==29646== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.

 ==29646== Using LibVEX rev 1732, a library for dynamic binary translation.

 ==29646== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.

 ==29646== Using valgrind-3.2.3, a dynamic binary instrumentation framework.

 ==29646== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.

 ==29646== For more details, rerun with: -v

 ==29646==

 ==29646==

 ==29646== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 1)

 ==29646== malloc/free: in use at exit: 10 bytes in 1 blocks.   //指示在程序退出时,还有多少内存没有释放。

 ==29646== malloc/free: 1 allocs, 0 frees, 10 bytes allocated. // 指示该执行过程malloc和free调用的次数。

 ==29646== For counts of detected errors, rerun with: -v // 提示如果要更详细的信息,用-v选项。

 ==29646== searching for pointers to 1 not-freed blocks.

 ==29646== checked 56,164 bytes.

 ==29646==

 ==29646== LEAK SUMMARY:

 ==29646==    definitely lost: 10 bytes in 1 blocks.

 ==29646==      possibly lost: 0 bytes in 0 blocks.

 ==29646==    still reachable: 0 bytes in 0 blocks.

 ==29646==         suppressed: 0 bytes in 0 blocks.

 ==29646== Rerun with --leak-check=full to see details of leaked memory.

 [konten@tencent test_valgrind]$

  以上结果中,红色的是手工添加的说明信息,其他是valgrind的输出。可以看到,如果我们仅仅用默认方式执行,valgrind只报告内存泄漏,但没有显示具体代码中泄漏的地方。

因此我们需要使用 “--leak-check=full”选项启动 valgrind,我们再执行一次:

 [konten@tencent test_valgrind]$ valgrind --leak-check=full ./memleak

 ==== Memcheck, a memory error detector.

 ==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.

 ==== Using LibVEX rev , a library for dynamic binary translation.

 ==== Copyright (C) -, and GNU GPL'd, by OpenWorks LLP.

 ==== Using valgrind-3.2., a dynamic binary instrumentation framework.

 ==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.

 ==== For more details, rerun with: -v

 ====

 ====

 ==== ERROR SUMMARY:  errors from  contexts (suppressed:  from )

 ==== malloc/free: in use at exit:  bytes in  blocks.

 ==== malloc/free:  allocs,  frees,  bytes allocated.

 ==== For counts of detected errors, rerun with: -v

 ==== searching for pointers to  not-freed blocks.

 ==== checked , bytes.

 ====

 ====  bytes in  blocks are definitely lost in loss record  of 

 ====    at 0x401A846: malloc (vg_replace_malloc.c:)

 ====    by 0x804835D: main (memleak.c:)

 ====

 ==== LEAK SUMMARY:

 ====    definitely lost:  bytes in  blocks.

 ====      possibly lost:  bytes in  blocks.

 ====    still reachable:  bytes in  blocks.

 ====         suppressed:  bytes in  blocks.

 [konten@tencent test_valgrind]$

  和上次的执行结果基本相同,只是多了上面蓝色的部分,指明了代码中出现泄漏的具体位置。

  以上就是用valgrind检查内存泄漏的方法,用到的例子比较简单,复杂的代码最后结果也都一样。

3.2 其他内存问题

我们下面的例子中包括常见的几类内存问题:堆中的内存越界、踩内存、栈中的内存越界、非法指针使用、重复free。

 #include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *ptr = malloc();
ptr[] = 'a'; // 内存越界 memcpy(ptr +, ptr, ); // 踩内存 char a[];
a[] = 'i'; // 数组越界 free(ptr); // 重复释放
free(ptr);
char *p1;
*p1 = ''; // 非法指针 return ;
}

编译:

 gcc -o invalidptr invalidptr.c -g

执行:

 valgrind --leak-check=full ./invalidptr

结果如下:

 [konten@tencent test_valgrind]$ valgrind --leak-check=full ./invalidptr

 ==== Memcheck, a memory error detector.

 ==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.

 ==== Using LibVEX rev , a library for dynamic binary translation.

 ==== Copyright (C) -, and GNU GPL'd, by OpenWorks LLP.

 ==== Using valgrind-3.2., a dynamic binary instrumentation framework.

 ==== Copyright (C) -, and GNU GPL'd, by Julian Seward et al.

 ==== For more details, rerun with: -v

 ====

 ==== Invalid write of size  //堆内存越界被查出来

 ====    at 0x80483D2: main (invalidptr.c:)

 ==== Address 0x4159034 is  bytes after a block of size  alloc'd

 ====    at 0x401A846: malloc (vg_replace_malloc.c:)

 ====    by 0x80483C5: main (invalidptr.c:)

 ====

 ==== Source and destination overlap in memcpy(0x4159029, 0x4159028, ) //踩内存

 ====    at 0x401C96D: memcpy (mc_replace_strmem.c:)

 ====    by 0x80483E6: main (invalidptr.c:)

 ====

 ==== Invalid free() / delete / delete[] //重复释放

 ====    at 0x401B3FB: free (vg_replace_malloc.c:)

 ====    by 0x8048406: main (invalidptr.c:)

 ==== Address 0x4159028 is  bytes inside a block of size  free'd

 ====    at 0x401B3FB: free (vg_replace_malloc.c:)

 ====    by 0x80483F8: main (invalidptr.c:)

 ====

 ==== Use of uninitialised value of size 

 ====    at 0x804840D: main (invalidptr.c:)

 ==== //非法指针,导致coredump

 ==== Process terminating with default action of signal  (SIGSEGV): dumping core

 ==== Bad permissions for mapped region at address 0x80482AD

 ====    at 0x804840D: main (invalidptr.c:)

 ====

 ==== ERROR SUMMARY:  errors from  contexts (suppressed:  from )

 ==== malloc/free: in use at exit:  bytes in  blocks.

 ==== malloc/free:  allocs,  frees,  bytes allocated.

 ==== For counts of detected errors, rerun with: -v

 ==== All heap blocks were freed -- no leaks are possible.

 Segmentation fault

 [konten@tencent test_valgrind]$

  从上面的结果看出,除了栈内存越界外,其他常见的内存问题都可以用valgrind简单的查出来。

3.3 显示代码覆盖

用callgrind工具能方便的显示程序执行的代码覆盖情况。

看如下例子:

3.4 显示线程竞态条件 <该版本暂不支持>

用helgrind工具可以在多线程代码中找到可能产生竞态条件的地方。

4.memcheck 工具的常用选型

4.1 leak-check

    --leak-check=<no|summary|yes|full> [default: summary]

    用于控制内存泄漏检测力度。

    no,不检测内存泄漏;

    summary,仅报告总共泄漏的数量,不报告具体泄漏位置;

    yes/full,报告泄漏总数、泄漏的具体位置

4.2 show-reachable

    --show-reachable=<yes|no> [default: no]

    用于控制是否检测控制范围之外的泄漏,比如全局指针、static指针等。

 #include <stdlib.h>
#include <stdio.h>
//char *gptr = NULL; int main(void)
{
gptr = (char *)malloc(); return ;
}

  对应以上代码,若--show-reachable为no,则valgrind不报告内存泄漏,否则会报告。

4.3 undef-value-errors

  --undef-value-errors=<yes|no> [default: yes]

  用于控制是否检测代码中使用未初始化变量的情况。

  对应以下代码:

1 int a;
2 printf("a = %d \n", a);

  若 --undef-value-errors=no,则valgrind不报告错误,否则报告“Use of uninitialised value ...”的错误。

4.4 其他选项

 --log-file=filename 将结果输出到文件。
--log-socket=192.168.0.1: 输出到网络。
--trace-children=<yes|no> [default: no]
--track-fds=<yes|no> [default: no]
--log-fd=<number> [default: , stderr]
--xml=<yes|no> [default: no]
--num-callers=<number> [default: ]
--show-below-main=<yes|no> [default: no]

5.Valgrind的编译安装

5.1 下载源代码

  下载地址http://valgrind.org/downloads/current.html#current ,截止目前为止,最新版本是3.2.3

5.2 编译

  编译,在源代码目录下执行:

 ./configure --prefix=[你自己的安装目录]
make;make install

便好了。

5.3 配置缺省选项

valgrind提供3种方式用于设置缺省选项:

a、~/.valgrindrc文件;

       b、环境变量$VALGRIND_OPTS;

       c、当前目录下的.valgrindrc文件;

       优先顺序为 a、b、c

   .valgrindrc的格式为:          

 --ToolName:OptionName=OptionVal

       如:

 --memcheck:leak-check=yes
--memcheck:show-reachable=yes

使用valgrind检查内存的更多相关文章

  1. 用valgrind检查内存问题

    Valgrind Valgrind作为一个免费且优秀的工具包,平时大部分人可能都是使用valgrind检测内存问题,如内存泄露,越界等. Valgrind工具包包含多个工具,如Memcheck,Cac ...

  2. 转: 使用valgrind检查内存问题

    作者:gfree.wind@gmail.com 博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net    本文的copyleft归gfree ...

  3. valgrind 检查内存泄露

    https://www.oschina.net/translate/valgrind-memcheck

  4. Linux 下用 valgrind 查找内存泄漏小例子

    1.安装 valgrind yum install valgrind 2.测试用例 main.cpp #include <iostream> using namespace std; st ...

  5. valgrind massif内存分析[转]

    valgrind检查内存泄露 #valgrind   ./程序 内存泄漏问题,我们有memcheck工具来检查.很爽.但是有时候memcheck工具查了没泄漏,程序一跑,内存还是狂飙.这又是什么问题. ...

  6. Valgrind检测内存泄露简介

    原文地址: Valgrind 概述 体系结构 Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合.Valgrind由内核(core)以及基于内核的其他调试工具组成.内核 ...

  7. Valgrind查找内存泄露利器

    Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析.你可以在它的环境中运行你的程序来监视内存的使用情况,比如C 语言中的ma ...

  8. valgrind调查内存leak

    快有几个月没更新了,记录一下最近解决问题用到的工具吧. 最近代码跑压力测试,总是发现内存在无规律的慢慢增加,因此在Android上用上了大名顶顶的valgrind,说实话,真是名不虚传, 真是建议以后 ...

  9. 用mtrace检查内存泄漏

    http://blog.csdn.net/ixidof/article/details/6638066内存泄漏检查方法(for Linux) 如果你更想读原始文档, 请参考glibc info的&qu ...

随机推荐

  1. Net设计模式实例之建造者模式(Builder Pattern)

    一.建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示. 建造者模式的优点是 ...

  2. 分离的思想结合单链表实现级联组件:CascadeView

    本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽可能地做到职责分离跟表现与行为分离,这个功能拆分成了2个组件并用到了单链表来实现关键的级联逻辑,下一段有演示效果的gif图.虽然这是个很常见 ...

  3. 【MVVM Light】新手初识MVVM,你一看就会

    一.前言 作为一个初入软件业的新手,各种设计模式与框架对我是眼花缭乱的.所以当我接触到这些新知识的时候就希望自己能总结几个步骤,以便更好更方便的在日常工作中进行使用. MVVM顾名思义就是Model- ...

  4. 初入网络系列笔记(1)TCP/IP基础

    一.借鉴说明,本博文借鉴以下博文 1.BlueTzar,TCP/IP四层模型, http://www.cnblogs.com/BlueTzar/articles/811160.html 2.叶剑峰,漫 ...

  5. jquery easyui使用(四)······添加,编辑,删除

    前端: <div style="font-size: 25px; font-weight: 700; margin: 50px 0 10px 10px;"> 车辆登记 ...

  6. PetaPoco4.0 实体某个字段不赋值会更新成null解决方案

    最新用PetaPoco4.0做项目发现有个需求,就是比如说:在mvc表单中,只显示部分字段,一个表单还有其他状态等字段,没有显示到mvc页面上 但是当MVC收集表单提交更新的时候,会发现会把数据库中的 ...

  7. 领域驱动设计常见问题FAQ

    本文出处:http://www.cqrs.nu/Faq What is a domain? The field for which a system is built. Airport managem ...

  8. Atitit.atiagent  agent分销系统 代理系统 设计文档

    Atitit.atiagent  agent分销系统 代理系统 设计文档 1. 启动项目1 2. 首也2 3. 登录功能2 4. 用户中心2 5. 充值查询3 6. 授权下级代理4 7. 我的提成5 ...

  9. jQuery实现鼠标经过图片变亮效果

    在线体验效果:http://hovertree.com/texiao/jquery/1.htm 以下是完整源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD ...

  10. UML 用例图、顺序图、状态图、类图、包图、协作图、流程图

    ​用例图.顺序图.状态图.类图.包图.协作图 面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是Unified Modeling La ...