淘宝商城(天猫)高级技术专家.3年研发+3年性能测试调优/系统测试+4年团队管理与测试架构、研发系统实践. 新舞台新气象, 深化测试基础架构及研发架构,希望能在某个技术领域成为真正的技术大牛。欢迎荐才http://bbs.51testing.com/viewthread.php?tid=120496&extra=&page=1 .邮件: jianzhao.liangjz@alibaba-inc.com,MSN:liangjianzhao@163.com.微博:http://t.sina.com.cn/1674816524

Valgrind 检测linux上c++内存泄露

上一篇 / 下一篇  2008-07-15 21:23:13 / 个人分类:搜索引擎测试技巧

查看( 5821 ) / 评论( 0 )
Linux c++上常用内存泄露检测工具有valgrind, Rational purify。Valgrind免费。Valgrind 可以在 32 位或 64 位 PowerPC/Linux 内核上工作。
Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。下面分别介绍个工具的作用:
Memcheck 工具主要检查下面的程序错误:
•        使用未初始化的内存 (Use of uninitialised memory)
•        使用已经释放了的内存 (Reading/writing memory after it has been free’d)
•        使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
•        对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
•        申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
•        malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
•        src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
Valgrind不检查静态分配数组的使用情况。
Valgrind占用了更多的内存--可达两倍于你程序的正常使用量。如果你用Valgrind来检测使用大量内存的程序就会遇到问题,它可能会用很长的时间来运行测试
2.1.        下载安装
http://www.valgrind.org
安装
./configure;make;make install
2.2.        编译程序
被检测程序加入 –g  -fno-inline 编译选项保留调试信息。

2.3.        内存泄露检测
$   valgrind --leak-check=full --show-reachable=yes --trace-children=yes       ./iquery  -f ../conf/se.conf_forum    -t  ~/eragon/forum_thread_data/f.log   -NT  -cache 0
其中--leak-check=full 指的是完全检查内存泄漏,--show-reachable=yes是显示内存泄漏的地点,--trace-children=yes是跟入子进程。当程序正常退出的时候valgrind自然会输出内存泄漏的信息。

==4591==
==4591== Thread 1:
==4591== Conditional jump or move depends on uninitialised value(s)
==4591==    at 0x805687B: main (TestQuery.cpp:478)
==4591==
==4591== Conditional jump or move depends on uninitialised value(s)
==4591==    at 0x8056894: main (TestQuery.cpp:478)
==4591==
==4591== Conditional jump or move depends on uninitialised value(s)
==4591==    at 0x80568AD: main (TestQuery.cpp:478)
==4591== Warning: set address range perms: large range 215212032 (noaccess)
==4591== Warning: set address range perms: large range 125145088 (noaccess)
==4591==
==4591== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 18 from 1)
==4591== malloc/free: in use at exit: 496 bytes in 2 blocks.
==4591== malloc/free: 928,605 allocs, 928,603 frees, 2,514,165,074 bytes allocated.
==4591== For counts of detected errors, rerun with: -v
==4591== searching for pointers to 2 not-freed blocks.
==4591== checked 10,260,564 bytes.
==4591==
==4591==
==4591== 144 bytes in 1 blocks are possibly lost in loss record 1 of 2
==4591==    at 0x4005906: calloc (vg_replace_malloc.c:279)
==4591==    by 0xB3671A: _dl_allocate_tls (in /lib/ld-2.3.4.so)
==4591==    by 0xD9491E: pthread_create@@GLIBC_2.1 (in /lib/tls/libpthread-2.3.4.so)
==4591==    by 0x8200C66: public_unit::CThread::start(void*) (Thread.cpp:25)
==4591==    by 0x80567C3: main (TestQuery.cpp:473)
==4591==
==4591==
==4591== 352 bytes in 1 blocks are still reachable in loss record 2 of 2
==4591==    at 0x40044F6: malloc (vg_replace_malloc.c:149)
==4591==    by 0xB9905E: __fopen_internal (in /lib/tls/libc-2.3.4.so)
==4591==    by 0xB9911C: fopen@@GLIBC_2.1 (in /lib/tls/libc-2.3.4.so)
==4591==    by 0x805940C: CSearchThread::run(void*) (TestQuery.cpp:363)
==4591==    by 0x8200D09: public_unit::CThread::thread_func(void*) (Thread.cpp:44)
==4591==    by 0xD94370: start_thread (in /lib/tls/libpthread-2.3.4.so)
==4591==    by 0xC0DFFD: clone (in /lib/tls/libc-2.3.4.so)
==4591==
==4591== LEAK SUMMARY:
==4591==    definitely lost: 0 bytes in 0 blocks.
==4591==      possibly lost: 144 bytes in 1 blocks.
==4591==    still reachable: 352 bytes in 1 blocks.
==4591==         suppressed: 0 bytes in 0 blocks.

关键字在:ERROR SUMMARY, LEAK SUMMARY
        "definitely lost" means your program is leaking memory -- fix it!
        "possibly lost" means your program is probably leaking memory, unless you're doing funny things with pointers.
        "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.
        "suppressed" means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors

另外一种方式,激活加载调试器
gcc -Wall   -g  -pg   -o get_XMLDOC  get_XMLDOC.c
$ valgrind   --db-attach=yes  --leak-check=full       ./get_XMLDOC   ~/eragon/data/offer_gb.xml  1.xml  10
==8956== Memcheck, a memory error detector.
==8956== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==8956== Using LibVEX rev 1606, a library for dynamic binary translation.
==8956== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==8956== Using valgrind-3.2.0, a dynamic binary instrumentation framework.
==8956== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==8956== For more details, rerun with: -v
==8956==
==8956==
==8956== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ----
==8956==
==8956== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)
==8956== malloc/free: in use at exit: 1,953 bytes in 2 blocks.
==8956== malloc/free: 4 allocs, 2 frees, 2,657 bytes allocated.
==8956== For counts of detected errors, rerun with: -v
==8956== searching for pointers to 2 not-freed blocks.
==8956== checked 52,840 bytes.
==8956==
==8956== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==8956==    at 0x40044F6: malloc (vg_replace_malloc.c:149)
==8956==    by 0x80488C0: main (get_XMLDOC.c:38)
==8956==
==8956== LEAK SUMMARY:
==8956==    definitely lost: 1 bytes in 1 blocks.
==8956==      possibly lost: 0 bytes in 0 blocks.
==8956==    still reachable: 1,952 bytes in 1 blocks.
==8956==         suppressed: 0 bytes in 0 blocks.
==8956== Reachable blocks (those to which a pointer was found) are not shown.
==8956== To see them, rerun with: --show-reachable=yes
Profiling timer expired

2.4.        检查性能瓶颈
$valgrind --tool=callgrind ./iquery  -f ../conf/se.conf_forum   -s "forum_thread?q=mp4"

==4607==
==4607== Events    : Ir
==4607== Collected : 251772397
==4607==
==4607== I   refs:      251,772,397

4607为进程号。
$ ll
-rw-------  1 search search   712159  7月  9 22:31 callgrind.out.4607
$ callgrind_annotate --auto=yes  callgrind.out.4607
WARNING: header line 2 malformed, ignoring
    line: 'creator: callgrind-3.2.0'
--------------------------------------------------------------------------------
I1 cache:
D1 cache:
L2 cache:
Timerange: Basic block 0 - 46942078
Trigger: Program termination
Profiled target:  ./iquery -f ../conf/se.conf_forum -s forum_thread?q=mp4 (PID 4607, part 1)
Events recorded:  Ir
Events shown:     Ir
Event sort order: Ir
Thresholds:       99
Include dirs:     
User annotated:   
Auto-annotation:  on

--------------------------------------------------------------------------------
         Ir
--------------------------------------------------------------------------------
251,772,397  PROGRAM TOTALS

--------------------------------------------------------------------------------
        Ir  file:function
--------------------------------------------------------------------------------
54,769,656  ???:__mcount_internal [/lib/tls/libc-2.3.4.so]
26,418,450  GBKNormalString.cpp:dictionary::CGBKNormalString::initNormalChars() [/home/search/eragon_yb/bin/iquery]
22,820,690  ???:mcount [/lib/tls/libc-2.3.4.so]
11,559,615  GBKNormalString.cpp:dictionary::CGBKNormalString::initCharKinds() [/home/search/eragon_yb/bin/iquery]

更多说明参考:
http://www-128.ibm.com/developerworks/cn/linux/l-pow-debug/

2.5.        cache测试
参考:http://www.wangcong.org/articles/valgrind.html
[search@alitest146 /home/search/eragon_yb/bin]
$ valgrind   --tool=cachegrind  ./iquery   -f ../conf/se.conf_forum   -s "forum_thread?q=mp3"
==8742==
==8742== I   refs:      267,968,791
==8742== I1  misses:         98,845
==8742== L2i misses:         13,382
==8742== I1  miss rate:        0.03%
==8742== L2i miss rate:        0.00%
==8742==
==8742== D   refs:      182,288,669  (120,222,370 rd + 62,066,299 wr)
==8742== D1  misses:        962,816  (    537,889 rd +    424,927 wr)
==8742== L2d misses:        707,813  (    340,925 rd +    366,888 wr)
==8742== D1  miss rate:         0.5% (        0.4%   +        0.6%  )
==8742== L2d miss rate:         0.3% (        0.2%   +        0.5%  )
==8742==
==8742== L2 refs:         1,061,661  (    636,734 rd +    424,927 wr)
==8742== L2 misses:         721,195  (    354,307 rd +    366,888 wr)
==8742== L2 miss rate:          0.1% (        0.0%   +        0.5%  )

上面的是指令缓存,I1和L2i缓存,的访问信息,包括总的访问次数,丢失次数,丢失率。
中间的是数据缓存,D1和L2d缓存,的访问的相关信息,下面的L2缓存单独的信息。Cachegrind也生成一个文件,名为cachegrind.out.pid,可以通过cg_annotate来读取。输出是一个更详细的列表。Massif的使用和cachegrind类似,不过它也会生成一个名为massif.pid.ps的PostScript文件,里面只有一幅描述堆栈使用状况的彩图。

[search@alitest146 /home/search/Isearchv3_Script_yb/tools]
$ ll  cachegrind.out*
-rw-------  1 search search  7283 Jul 11 11:21 cachegrind.out. 8633

$  cg_annotate  --8633  --auto=yes  ~/isearch_yb/src/test/core/TestQuery.cpp                                                      
--------------------------------------------------------------------------------
I1 cache:         16384 B, 32 B, 8-way associative
D1 cache:         16384 B, 64 B, 8-way associative
L2 cache:         2097152 B, 64 B, 8-way associative
Command:          ./iquery -f ../conf/se.conf_forum -s forum_thread?q=mp3
Data file:        cachegrind.out.8633
Events recorded:  Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
Events shown:     Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
Event sort order: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
Thresholds:       99 0 0 0 0 0 0 0 0
Include dirs:     
User annotated:   /home/search/isearch_yb/src/test/core/TestQuery.cpp
Auto-annotation:  on

--------------------------------------------------------------------------------
         Ir   I1mr   I2mr          Dr    D1mr    D2mr         Dw    D1mw    D2mw
--------------------------------------------------------------------------------
267,968,791 98,845 13,395 120,222,370 537,889 340,938 62,066,299 424,927 366,883  PROGRAM TOTALS

--------------------------------------------------------------------------------
        Ir  I1mr  I2mr         Dr    D1mr    D2mr         Dw    D1mw    D2mw  file:function
--------------------------------------------------------------------------------
56,779,152    28     6 14,194,788      82       3 14,194,788      34      13  ???:__mcount_internal
26,418,450   108    54 12,868,530  22,710   3,028  1,943,010  79,943  30,480  GBKNormalString.cpp:dictionary::CGBKNormalString::initNormalChars()

       
……
-- User-annotated source: get_XMLDOC.c
--------------------------------------------------------------------------------
    Ir I1mr I2mr    Dr D1mr D2mr    Dw D1mw D2mw

     .    .    .     .    .    .     .    .    .  #include "stdio.h"
     .    .    .     .    .    .     .    .    .  #define LINE_MAX_LEN  10240
     .    .    .     .    .    .     .    .    .  //get part of  xml
     .    .    .     .    .    .     .    .    .  main(int argc,char *argv[])
    10    1    1     0    0    0     1    0    0   {
     .    .    .     .    .    .     .    .    .       FILE *fp;
     1    0    0     0    0    0     1    0    0       FILE *fpDst =NULL;
     .    .    .     .    .    .     .    .    .      
     8    1    0     0    0    0     4    1    1       char content[LINE_MAX_LEN+1]={0};
     .    .    .     .    .    .     .    .    .       int  inumOfdocs;
     1    0    0     0    0    0     1    0    0       int  currentdocs=0;
     1    1    1     0    0    0     1    0    0       int  isDocBegin = 0;     
     1    0    0     0    0    0     1    0    0       int  isDocEnd = 0;
     .    .    .     .    .    .     .    .    .  
     2    0    0     1    0    0     0    0    0      if (argc < 4)
     .    .    .     .    .    .     .    .    .       {
     .    .    .     .    .    .     .    .    .        printf("usage: get_XMLDOC srcxml dstxml  numOfdocs\n");
     .    .    .     .    .    .     .    .    .        exit(1);
     .    .    .     .    .    .     .    .    .       }           
     .    .    .     .    .    .     .    .    .      
     7    2    1     2    0    0     3    0    0       inumOfdocs = atoi(argv[3]);
     2    0    0     1    0    0     0    0    0       if (inumOfdocs <=0 )

TAG:

我来说两句

(可选)

Open Toolbar