【原创】Valgrind 基础

Valgrind 概述

Valgrind 是一种用于构建动态分析工具集的框架; 
Valgrind 工具能够自动探测许多种类的内存管理 bug 和线程 bug ,能够帮助你在细微处进行程序调优; 
你可以基于 Valgrind 构建新工具集; 

Valgrind 当前发布版包含了六种产品质量相关工具: 

  • 一种内存错误探测器
  • 两种线程错误探测器
  • 一种 cache 和分支预测分析工具
  • 一种 call-graph generating cache 和分支预测分析工具
  • 一种堆分析工具

Valgrind 还包含了三种实验性工具: 

  • heap/stack/global 数组越界探测器
  • a second heap profiler that examines how heap blocks are used
  • a SimPoint basic block vector generator

Valgrind 与 CPU 、操作系统,以及编译器和基础 C 库都是强相关的;移植 Valgrind 是比较困难的。 
尽管如此,Valgrind 已经支持如下各种平台: 

  • - X86/Linux
  • - AMD64/Linux
  • - PPC32/Linux
  • - PPC64/Linux
  • - ARM/Linux
  • - x86/MacOSX
  • - AMD64/MacOSX
  • - S390X/Linux
  • - MIPS32/Linux
  • - MIPS64/Linux

Note that AMD64 is just another name for x86_64 , and Valgrind runs fine on Intel processors.   
Also note that the core of MacOSX is called " Darwin " and this name is used sometimes. 

Valgrind is licensed under the GNU General Public License, version 2. 
However: if you contribute code, you need to make it available as GPL version 2 or later, and not 2-only. 

Valgrind  源码安装

基于 tar.bz2 源码包的安装: 

  1. Run ./configure, with some options if you wish.  The only interesting one is the usual --prefix=/where/you/want/it/installed.
  2. Run "make".
  3. Run "make install", possibly as root if the destination permissions require that.
  4. See if it works.  Try "valgrind ls -l".  Either this works, or it bombs out with some complaint. 

Important !  Do not move the valgrind installation into a place different from that specified by --prefix at build time.  
This will cause things to break in subtle ways, mostly when Valgrind handles fork/exec calls. 

Valgrind 工具套装

The Valgrind distribution includes the following debugging and profiling tools: 

Memcheck 
Memcheck 用于探测程序中存在的内存管理问题,主要针对 C 和 C++ 程序; 
当程序运行在 Memcheck 监控之下时,所有针对内存的读写操作都将被检查,所有 malloc/new/free/delete 调用都会被拦截; 
因此,Memcheck 能够探测到你的程序是否存在以下的问题: 

  • Accesses memory it shouldn't (areas not yet allocated, areas that have been freed, areas past the end of heap blocks, inaccessible areas of the stack).
    访问了不该访问的内存(尚未分配过的区域;已经被释放掉的区域;超过堆块边界的区域;栈中不可访问的区域)
  • Uses uninitialised values in dangerous ways.
    以危险方式使用未初始化的值
  • Leaks memory.
    存在内存泄露
  • Does bad frees of heap blocks (double frees, mismatched frees).
    针对堆块执行了错误的 free 行为(double free 或 mismatched free)
  • Passes overlapping source and destination memory blocks to memcpy() and related functions.
    基于 memcpy() 或其他相关函数操作了存在重叠的源和目的地址所指向的内存块;

Memcheck 会在遇到上述错误的时候立即进行报告,同时给出错误发生对应的源码行号,以及触发该错误时对应的函数调用栈; 
Memcheck 是基于字节进行寻址跟踪,基于比特进行 value 的初始化跟踪;所以,其可以探测出单独一比特未初始化数据的使用,而不会作为比特运行错误进行报告; 
基于 Memcheck 运行程序时将会比常规运行慢 10-30 倍; 

Cachegrind 
Cachegrind 是一种 cache 分析工具; 
Cachegrind 能够针对 CPU 进行 I1, D1 和 L2 cache 的详细模拟,并精确的定位出代码中导致 cache miss 的地方; 
Cachegrind 能够确定出 cache miss 的次数、内存引用情况,以及会触发 cache miss 的每一行代码,每一个函数,每一个模块,并给出整个程序的情况摘要; 
Cachegrind 对于任何语言编写的程序都非常有用; 
基于 Cachegrind 运行程序时将会比常规运行慢 20-100 倍; 

Callgrind 
Callgrind 是针对 Cachegrind 的扩展; 
Callgrind 提供了 Cachegrind 所能提供的全部信息,还额外提供了关于 callgraphs 的信息; 
Callgrind 在 Valgrind 的 3.2.0 主发布版中被加入; 
另外还有一个名为 KCachegrind 的可视化工具,可以对 Callgrind 收集到的信息尽心更好的展示; 

Massif 
Massif 是一种堆分析工具; 
Massif 通过对程序堆获取常规快照,进而展开详细堆分析; 
Massif 能够生成随时间变化的堆使用图,其中会给出程序的哪些部分进行了绝大部分的内存分配操作; 
作为图的补充,通过 text 或 HTML 文件能够确定分配内存最多地方的更多信息; 
基于 Massif 运行程序时将会比常规运行慢 20 倍; 

Helgrind 
Helgrind 是一种线程调试器,用于查找多线程程序中的数据竞争; 
Helgrind 会查出特定类型内存的位置:被多于一个(POSIX p-)thread 所访问,但是却没有发现保证访问一致性的锁; 
这类位置已经隐式表明了多线程同步的缺失,将会导致非常难于发现的时序问题; 
Helgrind 对于任何使用 pthreads 的程序都非常有用; 

DRD 
DRD 是一种检测多线程 C 和 C++ 程序错误的工具; 
DRD 对于任何使用 POSIX 线程原语的程序有效;或对于任何构建与 POSIX 线程原语之上的、使用线程概念的程序有效; 
尽管 Helgrind 能够检测出锁定顺序违反等问题,但对于大部分程序来说,DRD 在进行分析时将花费更少的内存; 

Lackey, Nulgrind 
Lackey and Nulgrind are also included in the Valgrind distribution. They don't do very much, and are there for testing and demonstrative purposes. 

Other Tools 
Several other Valgrind tools have been created: you can find a list of them on the Variants / Patches page. 

FAQ 摘译

1.1. How do you pronounce "Valgrind"? 
The "Val" as in the word "value". The "grind" is pronounced with a short 'i' -- ie. "grinned" (rhymes with "tinned") rather than "grined" (rhymes with "find"). 

4.4. My program crashes normally, but doesn't under Valgrind, or vice versa. What's happening? 
基于 valgrind 运行目标程序和直接运行目标程序两种方式存在些许不同;例如,内存布局会不同线程调度方式会不同。 

      在大多数情况下,上述差异不会导致什么问题,但当你的程序本身存在 bug 的时候,可能会遇到一些问题。例如,如果你的程序原本会崩溃于错误的访问了非法内存地址的情况,而在基于 valgrind 运行时可能,该地址可能就是合法的内存地址了。另一种情况是,如果你的程序存在数据竞争,但在 valgrind 下可能不会显现出来。 

      对于上面的情况,你是无法做出任何应对的,因为这就是 valgrind 的工作方式,即 valgrind 无法精确的复制出可执行程序的本地执行环境。当出现你的程序崩溃于内存错误,但在 valgrind 下无法出现时,大多数情况下,Memcheck 工具应该都能检测出错误的内存操作。 

4.5. Memcheck doesn't report any errors and I know my program has errors. 
产生上述问题可能有两种原因。 

      首先,默认情况下,valgrind 只会跟踪 top-level 进程,因此,如果你的程序会创建子进程,则默认情况下,子进程 不会被 valgrind 所跟踪。同样的,如果你的程序时通过 shell 脚本、Perl 脚本,或者其他类似的脚本启动的,那么 valgrind 将会跟踪 shell 或 Perl 解析器,或其他类似的东西。 

为了跟踪子进程,需要使用  --trace-children=yes 选项。 

      如果你打算跟踪的进程是由很多进程构成,最好的方式是将输出结构通过网络发送到某处。可以通过指定  --log-socket=127.0.0.1:12345 选项(将输出结果发送到本地 12345 端口)达成此目的。 你可以使用  valgrind-listener 程序建立该端口的监听。 

valgrind-listener 12345

当然,你必须事先启动监听进程才能正常工作。 

      其次,大多数 valgrind 工具的工作模式为,通过替换程序中的某些函数,例如 malloc ,为自定义版本,来达成探测和分析的目的 ,如果你的程序是静态链接的 ,则不会进程这种替换,从而无法进程有效的检测。例如,可能从 Memcheck 输出中看到输出 

All heap blocks were freed -- no leaks are possible

而实际上,你明确知道自己调用了 malloc 。解决办法就是使用  --soname-synonyms=somalloc=NONE 设置,或者在目标程序中避免使用静态链接。 

      还存在另外一种无法进行替换的情况,即使用了另外一种 malloc 库,例如 tcmalloc 或 jemalloc 等。在这种情况下,需要通过指定  --soname-synonyms=somalloc=zzzz 选项(其中 zzzz 为替换用的  malloc 库的 soname),以允许 valgrind 进行相应替换。 

4.6. Why doesn't Memcheck find the array overruns in this program? 

int static[5];

int main(void)
{
    int stack[5];

    static[5] = 0;
    stack [5] = 0;

    return 0;
}

非常不幸的是,Memcheck 无法针对全局数组或栈数组进行边界检查。我们很想做到,但是目前尚未找到一种合理的实现方式,令这种检查与 Memcheck 的工作方式相符,所以,非常抱歉。 
然而,实验工具  SGcheck 能够探测出这种错误。 你可以通过指定  --tool=exp-sgcheck 选项运行 valgrind 进程相关检查,唯一需要明确的是,该工具可能没有 Memcheck 那么健壮。 

5.2. With Memcheck's memory leak detector, what's the difference between "definitely lost", "indirectly lost", "possibly lost", "still reachable", and "suppressed"? 
详细信息可以参见用户手册中的 Memcheck 章节。 
简要说明如下: 

  • "definitely lost" 意味着你的程序一定存在内存泄露;
  • "indirectly lost" 意味着你的程序一定存在内存泄露,并且泄露情况和指针结构相关(例如,如果二叉树的根节点被判定为"definitely lost",则其所有子节点将被判定为"indirectly lost");如果你正确修复了类型为 "definitely lost" 的泄露,那么类型为 "indirectly lost" 的泄露应该会随着消失;
  • "possibly lost" 意味着你的程序一定存在内存泄露,除非你是故意进行着不符合常规的操作,例如将指针指向某个已分配内存块的中间位置。参见用户手册查询一些可能的情况。可以指定 --show-possibly-lost=no 选项屏蔽掉这类报告信息。
  • "still reachable" 意味着你的程序可能是没问题的,但确实没有释放掉一些本可以释放的内存。这种情况是很常见的,并且通常基于合理的理由。 可以通过 --show-reachable=yes 选项控制是否输出相应的报告信息。
  • "suppressed" 意味着有些泄露信息被压制了。在默认的 suppression 文件中可以看到一些 suppression 相关设置。理论上讲,你可以忽略这类错误。

5.4. Is it possible to attach Valgrind to a program that is already running? 
不可以,因为 valgrind 为程序运行使用了完全不同的环境设置,例如采用了不同的内存布局方案等。所以 valgrind 需要在程序启动伊始就进行完全控制。

It is possible to achieve something like this by running your program without any instrumentation (which involves a slow-down of about 5x, less than that of most tools), and then adding instrumentation once you get to a point of interest. Support for this must be provided by the tool, however, and Callgrind is the only tool that currently has such support. See the instructions on the callgrind_control program for details. 

实验输出

[root@Betty ~]#
[root@Betty ~]# valgrind ls -l
==23285== Memcheck, a memory error detector
==23285== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==23285== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==23285== Command: ls -l
==23285==
总用量 504
-rw-------.  1 root root   1676 3月  10 2014 anaconda-ks.cfg
...
==23285==
==23285== HEAP SUMMARY:
==23285==     in use at exit: 20,296 bytes in 33 blocks
==23285==   total heap usage: 266 allocs, 233 frees, 99,073 bytes allocated
==23285==
==23285== LEAK SUMMARY:
==23285==    definitely lost: 0 bytes in 0 blocks
==23285==    indirectly lost: 0 bytes in 0 blocks
==23285==      possibly lost: 0 bytes in 0 blocks
==23285==    still reachable: 20,296 bytes in 33 blocks
==23285==         suppressed: 0 bytes in 0 blocks
==23285== Rerun with --leak-check=full to see details of leaked memory
==23285==
==23285== For counts of detected and suppressed errors, rerun with: -v
==23285== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
[root@Betty ~]#
[root@Betty ~]# 
时间: 2024-08-24 05:08:08

【原创】Valgrind 基础的相关文章

原创Hadoop基础题库

原本想出至少50题hadoop, HDFS, MapReduce, Zookeeper相关的基础题,现在暂时不进行了,把已经出的20多道题都奉上. 暂时没有了出题的动力,可能觉得这东西出成题也没啥意义.总之权当巩固,各位权当消遣着瞧瞧. //Hadoop基础 Doug Cutting所创立的项目的名称都受到其家人的启发,以下项目不是由他创立的项目是 A. Hadoop B. Nutch C. Lucene D. Solr 答案:D 配置Hadoop时,JAVA_HOME包含在哪一个配置文件中 A

javascript typeof id==='string'?document.getElementById(id):id解释[原创]_基础知识

一般来说想要理解这段代码,需要掌握如下两个函数 一个是 typeof 一个就是三元运算符 看完了上面的文章再看下面的就比较好理解了 一般来说常用的函数代码 function $(id){ return typeof id==='string'?document.getElementById(id):id;} var GetBy = function (id) { return "string" == typeof id ? document.getElementById(id) : i

站长感慨asp编程究竟何去何从[原创]_ASP基础

令人抱憾的一个现象,今天一个同事说我的网络编程栏目下的asp编程,竟然没有带来任何ip,我的站的好多asp编程资料都是手工从各大比较好的asp编写的系统中提取出来的asp的精华代码,网上转载了我的全站信息的网站有很多,我的站的asp编程,asp下fso操作,asp小偷与采集,asp class类的都是精品文章,其中asp基础更是包括了6大对象等基础学习资料,希望能给学习asp编程类的朋友带来一定的便利,而且我要说的是,大家如果来学asp的基础编程,那么我可以负责任的告诉大家,大家如果还在到底学a

ASP.NET中Literal控件的使用方法[原创]_基础应用

可以将 Literal 控件用作网页上其他内容的容器.Literal 控件最常用于向网页中动态添加内容.简单的讲,就是可以把 HTML 代码写到 Literal 控件上,直接呈现出来. 一.常见Literal属性 属性 描述 Text 指定 Literal 控件中显示的文本.在用户的浏览器中,这会显示为 HTML. Mode 指定控件如何处理添入其中的标记. 二.基础用法 前台 LiteralTest.aspx 复制代码 代码如下: <asp:Literal ID="Literal1&qu

完美解决ASP 不能更新。数据库或对象为只读。[原创]_ASP基础

最近帮别人处理下数据,发现添加数据时,就提示"ASP 不能更新.数据库或对象为只读.",从网上找了,也没有解决我的问题.1.服务器的数据目录mdb文件所在的目录,是只读的2.数据库在本地的权限,去只读权限,再上传3.有可能你是从只读目录移动到可读目录的,所以一定不能这么用,先下到本地,再上传,可解决此类问题.www.jb51.net "不能更新,数据库或对象为只读"的解决方案 初接触dreamweaver,在做一简单页面实现向access数据库写数据时,总是遇到这样

后缀就扩展名为js的文件是什么文件[原创]_基础知识

好多朋友刚开始接触网络,不懂后缀为js的文件,是什么文件,其实这个扩展名为.js的文件就是javascript文件,为什么要用<script src="test.js"></script>的格式来调用文件呢,其实我们经常在做网页过程中,因为js文件如果写到网页中,不利于我们的反复修改,如果以后我们需要修改js文件的话,就可以直接改js文件,不需要改整个网页,现在大家的网站都是生成静态的html,如果要修改成千上万的个静态页面,不论是替换还是从节约网站空间,都是不

如何回到先前的页面的方法多中语言[原创]_ASP基础

asp: 复制代码 代码如下: <a href="<%=request.serverVariables("Http_REFERER")%>">preivous page</a>或用图片如:<img src=http://www.host01.com/Get/asp/00010006/"arrowback.gif" alt="<%=request.serverVariables("

一个多文件上传的例子(原创)_php基础

<?//filename:multi_upload.phpif($ifupload){  $path=AddSlashes(dirname($PATH_TRANSLATED))."\\upload\\";  for($i=1;$i<=8;$i++)  {     $files="afile".$i;     if(${$files}!="none")     {        if(copy(${$files},$path.${$fi

保存的js无法执行的解决办法[原创]_基础知识

好多新手,对于保存的js无法运行,或直接就是用记事本之类的软件打开,而我们需要看到的是执行效果,我们经常用记事本或eidtplus手写的同志,基本上都是让js后缀的脚本用文本打开,如果突然想让它执行,怎么办呢,方法呢有两个1.比较根本的解决就是:例如run.js,我们直接在这个文件上右键->调出打开方式--选择程序--浏览到系统盘(假如是c盘)找到c:\windows(或winnt)\system32\wscript.exe即可2.直接将run.js的改成run.jse,这样更容易运行