valgrind和Kcachegrind性能分析工具详解

一、valgrind介绍

valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,用于构建动态分析工具的装备性框架。它包括一个工具集,每个工具执行某种类型的调试、分析或类似的任务,以帮助完善你的程序。Valgrind的架构是模块化的,所以可以容易的创建新的工具而又不会扰乱现有的结构。

valgrind主要包含以下工具:

1、memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。 2、callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。 3、cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。 4、helgrind:用于检查多线程程序的竞态条件。 5、massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

另外,也有一些大多数用户不会用到的小工具: Lackey是一个示例工具,用于演示一些装备的基础性内容;Nulgrind是一个最小化的Valgrind工具,不做分析或者操作,仅用于测试目的。

二、valgrind安装及使用 安装

建议从valgrind官网下载安装,目前官网的最新包是3.16.1

$ mkdir valgrind-inst $ cd valgrind-inst/ $ wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2 $ ls valgrind-3.16.1.tar.bz2

解压后进行安装,可以指定安装目录,这样的话记得设置环境变量

$ tar -xvf valgrind-3.16.1.tar.bz2 $ cd valgrind-3.16.1 $ ./configure --prefix=http://www.likecs.com/usr/local/valgrind $ make $ make install

查看是否安装成功

$ valgrind --version valgrind-3.16.1 工具集的使用

基本使用格式如下:

usage: valgrind [options] prog-and-args

其支持众多选项,我们可以通过valgrind --help来进行查看。

这里我们只介绍几个较为常用的选项

--tool: 是最常用的选项,用于选择使用valgrind工具集中的哪一个工具。默认值为memcheck。 --version: 用于打印valgrind的版本号 -q/--quiet: 安静的运行,只打印错误消息; -v/--verbose: 打印更详细的信息; --trace-children: 是否跟踪子进程,默认值为no; --track-fds: 是否追踪打开的文件描述符,默认为no --time-stamp=no|yes: 是否在打印出的每条消息之前加上时间戳信息。默认值为no --log-file=<file>: 指定将消息打印到某个文件 --default-suppressions: 加载默认的抑制参数。 --alignment: 指定malloc分配内存时的最小对齐字节数; 如下的一些选项用于Memcheck工具: --leak-check=no|summary|full: 在退出时是否查找内存泄露。默认值为summary --show-leak-kinds=kind1,kind2,..: 显示哪一种类型的内存泄露。默认显示definite和possible这两种; 三、 Valgrind 工具详解 1) memcheck

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

1、使用未初始化的内存。如果在定义一个变量时没有赋初始值,后边即使赋值了,使用这个变量的时候Memcheck也会报"uninitialised value"错误。使用中会发现,valgrind提示很多这个错误,由于关注的是内存泄漏问题,所以可以用--undef-value-errors=选项把这个错误提示屏蔽掉,具体可以看后面的选项解释。 2、读/写释放后的内存块; 3、内存读写越界(数组访问越界/访问已经释放的内存),读/写超出malloc分配的内存块; 4、读/写不适当的栈中内存块; 5、内存泄漏,指向一块内存的指针永远丢失; 6、不正确的malloc/free或new/delete匹配(重复释放/使用不匹配的分配和释放函数); 7、内存覆盖,memcpy()相关函数中的dst和src指针重叠。

用法:

将程序编译生成可执行文件后执行:valgrind –leak-check=full ./程序名

注意:下面讨论的所有测试代码在编译时最好都加上-g选项(用来在memcheck的输出中生成行号)进行编译。

测试程序验证:

编写测试程序

#include <stdlib.h> void func() { char *p = new char[10]; } int main() { func(); return 0; }

编译后,用valgrind检测程序。
如果设置了--leak-check=full,Memcheck会给出详细的每个块是在哪里分配,并且给出分配时函数调用堆栈(编译的时候使用-g选项和去掉-o优化选项,就可以得到更详细的函数信息,可以精确到代码的某一行)。可以通过--show-leak-kinds选项来选择要详细报告哪几种类型的错误。Memcheck会把函数调用堆栈相同或相似的内存块信息,放到同一个条目来显示,可以通过--leak-resolution来控制这个"相似"判断的力度。

$ g++ -g -o test leak.cpp $ valgrind --tool=memcheck --leak-check=full ./test

检测结果如下:

==6018== Memcheck, a memory error detector ==6018== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==6018== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info ==6018== Command: ./test ==6018== ==6018== ==6018== HEAP SUMMARY: ==6018== in use at exit: 10 bytes in 1 blocks ==6018== total heap usage: 1 allocs, 0 frees, 10 bytes allocated ==6018== ==6018== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==6018== at 0x4C2AC58: operator new[](unsigned long) (vg_replace_malloc.c:431) ==6018== by 0x40062E: func() (leak.cpp:4) ==6018== by 0x40063D: main (leak.cpp:8) ==6018== ==6018== LEAK SUMMARY: ==6018== definitely lost: 10 bytes in 1 blocks ==6018== indirectly lost: 0 bytes in 0 blocks ==6018== possibly lost: 0 bytes in 0 blocks ==6018== still reachable: 0 bytes in 0 blocks ==6018== suppressed: 0 bytes in 0 blocks ==6018== ==6018== For lists of detected and suppressed errors, rerun with: -s ==6018== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

结果说明:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspfdx.html