跳转至

valgrind

valgrind一款内存检测工具,包括如下模块 1. Memcheck:是一个内存错误检测器。对未初始化内存的使用;读/写释放后的内存块;读/写超出malloc分配的内存块;读/写不适当的栈中内存块;内存泄漏,指向一块内存的指针永远丢失;不正确的malloc/free或new/delete匹配;memcpy()相关函数中的dst和src指针重叠 2. Cachegrind: 是一个缓存和分支预测分析器。它可以帮助您使程序运行得更快。它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。 3. Callgrind: 是一个调用图生成缓存分析器。它与 Cachegrind 有一些重叠,但也收集了一些 Cachegrind 没有的信息。 4. Helgrind:是一个线程错误检测器。它可以帮助您使您的多线程程序更正确。锁检测。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误 5. DRD:也是一个线程错误检测器。它与 Helgrind 类似,但使用不同的分析技术,因此可能会发现不同的问题。 6. Massif:是一个堆分析器。它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小,它可以帮助您使程序使用更少的内存。 7. DHAT:是一种不同类型的堆分析器。它可以帮助您了解块生命周期、块利用率和布局效率低下的问题。 8. BBV:是一个实验性的 SimPoint 基本块向量生成器。它对从事计算机体系结构研究和开发的人很有用。

1 安装

  1. 下载源码包(https://valgrind.org/downloads/current.html),解压缩(tar –jxvf valgrind.tar.bz2)
  2. 根据源码目录下的README文件,源码安装,可能需要安装automakeautoconf
    1. yum install -y autoconf automake
To install from the GIT repository:

  0. Clone the code from GIT:
     git clone git://sourceware.org/git/valgrind.git
     There are further instructions at
     http://www.valgrind.org/downloads/repository.html.

  1. cd into the source directory.

  2. Run ./autogen.sh to setup the environment (you need the standard
     autoconf tools to do so).

  3. Continue with the following instructions...

To install from a tar.bz2 distribution:

  4. Run ./configure, with some options if you wish.  The only interesting
     one is the usual --prefix=/where/you/want/it/installed.

  5. Run "make".

  6. Run "make install", possibly as root if the destination permissions
     require that.

  7. See if it works.  Try "valgrind ls -l".  Either this works, or it
     bombs out with some complaint.  In that case, please let us know
     (see http://valgrind.org/support/bug_reports.html).

2 valgrind 通用命令行选项

  • 语法:valgrind [valgrind-options] your-prog [your-prog-options] valgrind 输出的第一列是进程号,第2列是检测信息,如输出结果
==12345== some-message-from-Valgrind

2.1 --tool

  • 功能:指定使用的valigrind提供的哪一种工具,memcheck(默认),cachegrind, callgrind, helgrind, drd, massif, dhat, lackey
  • 格式:--tool=<toolname> [default: memcheck]

2.2 --trace-children

title: 其实是跟踪exec调用的程序,而不是子进程
Note that Valgrind does trace into the child of a `fork` (it would be difficult not to, since `fork` makes an identical copy of a process), so this option is arguably badly named. However, most children of `fork` calls immediately call `exec` anyway.
  • 功能:跟踪子进程(exec system call),在多进程中开启
  • 格式:--trace-children=<yes|no> [default: no]

2.3 --time-stamp

  • 功能:每条消息前面都会显示自启动以来经过的挂钟时间,没字段分别是 days, hours, minutes, seconds and milliseconds
  • 格式:--time-stamp=<yes|no> [default: no]
  • 示例:下面257是毫秒,前面的00,分别是 days, hours, minutes, seconds
[root@centos7 Valgrind]# valgrind --time-stamp=yes ./a.out 
...
==00:00:00:00.000 1597== Command: ./a.out
==00:00:00:00.000 1597== 
==00:00:00:00.257 1597== Invalid write of size 4
==00:00:00:00.257 1597==    at 0x40054E: f() (test.cc:6)
==00:00:00:00.257 1597==    by 0x40055E: main (test.cc:11)
...

2.4 --track-fds

  • 功能:
  • 格式:

2.5 --log-fd

  • 功能:指定valgrind将所有消息发送到指定的文件描述符
  • 格式:--log-fd=<number> [default: 2, stderr]

2.6 --log-file

  • 功能:指定valgrind将所有消息写入到指定的文件中
  • 格式:--log-file=<filename>,其中支持以下几个格式
    • %p:表示进程id,通常在多进程中很有用,多个进程的消息分别写入自己的文件中
    • %n:被替换为此进程唯一的文件序列号。这对于从同一文件名模板生成多个文件的进程很有用。
[root@centos7 Valgrind]# valgrind --log-file=file-%p ls
[root@centos7 Valgrind]# ll file*
-rw-r--r--. 1 root root 915 Aug  7 20:12 file-2291

2.7 --log-socket

  • 功能:将输出写入指定的socket上,如果不指定端口,默认是1500。可以通过使用valgrind-listener 来监听客户端valgrind发送过来的信息
  • 格式:--log-socket=<ip-address:port-number>

2.8 --vgdb

具体操作见(https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver)
  • 功能:允许外部 GNU GDB 调试器在 Valgrind 上运行时控制和调试程序
  • 格式:--vgdb=<no|yes|full> [default: yes]

2.9 --main-stacksize

  • 功能:指定主线程堆栈的大小。默认使用当前ulimit设置的值
  • 格式:--main-stacksize=<number> [default: use current 'ulimit' value]

2.10 --max-threads

  • 功能:指定valgrind支持的最大线程数。默认是500个线程
  • 格式:--max-threads=<number> [default: 500]

2.11 memcheck内存泄漏检测

通过指定--tool=memcheck(默认)来启用memcheck - 选项 - --leak-check=<no|summary|yes|full> [default: summary]:当设置成summary时,仅统计内存泄漏数量,yes|full会显示详细信息 - --show-leak-kinds=<set> [default: definite,possible]:指定需要显示的内存泄漏类型 - 可选类型有:definite indirect possible reachable none all;all相当于definite indirect possible reachable

3 valgrind-listener

  • 功能:监听来自valgrind通过socket发送过来的信息
  • 语法:valgrind-listener [options]
    • -e --exit-at-zero:当连接的进程数回落到零时,退出。没有这个,它将永远运行,也就是说,直到你发送它 ctrl+c。
    • --max-connect=整数:默认情况下,监听器最多可以连接 50 个进程。有时,这个数字太小了。使用此选项可提供不同的限制。例如。 --最大连接=100。
    • portnumber:将其侦听的端口从默认值 (1500) 更改。指定的端口必须在 1024 到 65535 的范围内。同样的限制适用于由 --log-socket 指定到 Valgrind 本身的端口号。
  • 示例步骤
    1. 先启动一个终端,启动监听valgrind-listener
    2. 在启动一个终端,启动valgrind检查,比如valgrind --log-socket=192.168.211.7 ls
    3. 查看终端1是否接收到来自终端2发送的信息
### 终端2,启动valgrind检查ls
[root@centos7 Valgrind]# valgrind --log-socket=192.168.211.7 ls 
### 终端1,启动监听,当终端2执行命令后,终端1收到消息
[root@centos7 ~]# valgrind-listener 
valgrind-listener started at Sun Aug  7 22:40:55 2022

(1) -------------------- CONNECT --------------------
(1)
(1) ==2683== Memcheck, a memory error detector
(1) ==2683== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
(1) ==2683== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
(1) ==2683== Command: ls
(1) ==2683== 
(1) ==2683== 
(1) ==2683== HEAP SUMMARY:
(1) ==2683==     in use at exit: 19,916 bytes in 10 blocks
(1) ==2683==   total heap usage: 44 allocs, 34 frees, 56,463 bytes allocated
(1) ==2683== 
(1) ==2683== LEAK SUMMARY:
(1) ==2683==    definitely lost: 0 bytes in 0 blocks
(1) ==2683==    indirectly lost: 0 bytes in 0 blocks
(1) ==2683==      possibly lost: 0 bytes in 0 blocks
(1) ==2683==    still reachable: 19,916 bytes in 10 blocks
(1) ==2683==         suppressed: 0 bytes in 0 blocks
(1) ==2683== Rerun with --leak-check=full to see details of leaked memory
(1) ==2683== 
(1) ==2683== For lists of detected and suppressed errors, rerun with: -s
(1) ==2683== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
(1) 
(0) ------------------- DISCONNECT -------------------
(0)

4 valgrind 使用注意事项

  1. 您应该在此处运行真正的(机器代码)可执行文件。例如,如果您的应用程序是由 shell 或 Perl 脚本启动的,则需要对其进行修改以在真正的可执行文件上调用 Valgrind。直接在 Valgrind 下运行此类脚本将导致您收到与 /bin/sh、/usr/bin/perl 或您正在使用的任何解释器有关的错误报告。这可能不是您想要的并且可能会造成混淆。您可以通过提供选项 --trace-children=yes 来强制解决此问题,但仍有可能造成混淆