您的位置:首页 > 编程语言 > C语言/C++

内存泄漏检查工具valgrind的安装与使用

2015-08-20 16:47 513 查看
转自:http://blog.chinaunix.net/uid-26000296-id-4161684.html

一、 安装

1. autoconf
# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz  # tar -zxvf autoconf-2.69.tar.gz 
# cd autoconf-2.69
# ./configure
# make; make install

2. automake
# wget http://ftp.gnu.org/gnu/automake/automake-1.14.tar.gz # tar -zxvf automake-1.14.tar.gz 
# cd automake-1.14
# ./bootstrap.sh
# ./configure
# make; make install

3. valgrind
# wget http://valgrind.org/downloads/valgrind-3.9.0.tar.bz2 # tar -jxvf valgrind-3.9.0.tar.bz2
# cd valgrind-3.9.0
# ./autogen.sh
# ./configure
# make; make install

二、快速使用指南
1. 简介
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件工具套装。
它最流行的工具是Memcheck, 它能检测C/C++中大部分的内存相关的错误。

2. 准备要检查的程序
程序编译时使用 “-g”参数,以添加调试信息,这样Memcheck的错误消息可以精确到行;
编译时使用“-O0”也有必要,只是速度会很慢,“-O1”可能会导致Memecheck的错误消息不正确;

3. 在Memcheck下运行程序: 
如果你的程序的运行命令如下:
  myprog arg1 arg2

则使用如下命令行:
  valgrind --leak-check=yes myprog arg1 arg2

Memcheck是valgrind默认的工具,"--leak-check"选项开启了详细内存泄漏检测器;
这时程序会比平时运行得慢很多(如,慢20~30倍),并且会消耗更多的内存;
程序运行结束后,或你用“CTRL+C”中止程序后,Memcheck将会列出检测到的内存出错和泄漏的信息;

4. Memcheck输出信息示例说明
下面是一个很简单的示例C程序,并带有一个内存错误和一个内存泄漏;
文件名为:a.c  
1   #include 

3   void f(void)
4   {
5      int* x = malloc(10 * sizeof(int));
6      x[10] = 0;                          // problem 1: heap block overrun
7   }                                            //
problem 2: memory leak -- x not freed
8
9   int main(void)
10 {
11   f();
12   return 0;
13 }

Most error messages look like the following, which describes problem 1, the heap block overrun:
错误消息如下,描述了问题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..."),说明了是哪种类型的错误;
  在这里,是程序写越界了
. 第一行之下的行都是函数调用栈跟踪,说明了问题的发生的地方;
  函数调用栈可以很大,如果还使用了C++ STL时,更容易使人混乱;从底向上读有助于理解;
  如果函数调用栈不够大,可以使用--num-callers选项来扩大;
. 代码地址(eg. 0x804838F)通常不用关心,有时只是在跟踪怪异的bug时有用;
. 有些错误信息有第二个组成部分,包括内存地址的描述等;
  在这个例子中,这部分的信息描述了写内存位于第五行的块分配函数malloc()之后.

按照报告的顺序修正错误很有必要,因为后面的错误可能是前面的错误造成的;
如果不这么做,会导致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)

函数调用栈说明了泄漏的内存是在哪分配的;
但是,Memcheck并不能说明为什么内存泄漏的(忽略"vg_replace_malloc.c",它只是一个实现细节);
有多种类型的内存泄漏,最重要是如下:
. "definitely lost": 你的程序内存泄漏了  -- 需要解决它;
. "probably lost":   你的程序内存泄漏了,可能需要解决;
  除非你对指针做了一些特殊的处理(如将其指向堆的中部)

Memcheck同样会报告未初始化值的使用,
对于这种情况,通常的消息是"Conditional jump or move depends on uninitialised value(s)"; 
追踪这种错误的根源可能很难;
可以尝试使用 “--track-origins=yes”选项来输出额外的信息;
但这会使Memcheck运行得更慢,但有可能追查到未初始化值的根源;






valgrind still reachable 的解释

示例测试结果如下:

==4445== HEAP SUMMARY:
==4445==     in use at exit: 554 bytes in 20 blocks
==4445==   total heap usage: 59 allocs, 39 frees, 14,056 bytes allocated
==4445==
==4445== LEAK SUMMARY:
==4445==    definitely lost: 0 bytes in 0 blocks
==4445==    indirectly lost: 0 bytes in 0 blocks
==4445==      possibly lost: 0 bytes in 0 blocks
==4445==    still reachable: 554 bytes in 20 blocks
==4445==         suppressed: 0 bytes in 0 blocks


相关说明:

"still reachable" means your program is probably ok -- it didn't free some memory it could have. This is quite common and often reasonable. Don't use --show-reachable=yes
if you don't want to see these reports.说这个程序可能是好的;

网上给的说法:

A、应该说不是memory
leak。

一些商业库都会分配自己的工作数据区,频繁调用时可能会多分配一些,而且不一定释放,但有限额。
程序7x24小时运行时,内存稳定到一定的大小,不算内存泄露。
建议使用更好的商业软件,如parasoft insure++或ibm rational purifyplus。花钱在这些软件上,值。 

B、still reachable 指的是内存指针还在 还有机会使用或者释放

如果你后面的程序不用或者不释放也会泄漏 valgrind在当时还不知道以后会不会泄漏 
C、多数情况不是问题,比如程序是一个服务,一直运行一个while循环,而new出来的对象如果只能在析构delete,那么对象就永远不会被释放,valgrind就会报这样的问题

但是从打印报告这句话:“in use at exit: 554 bytes
in 20 blocks
total heap usage: 59 allocs, 39 frees, 14,056 bytes allocated”,知道还是20
allocs没有回收,还是用内存泄露;

经过查找,果真有地方没有free。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C c++ 内存泄露