码迷,mamicode.com
首页 > 编程语言 > 详细

C/C++内存泄露检测

时间:2016-04-16 23:13:11      阅读:1189      评论:0      收藏:0      [点我收藏+]

标签:

gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

一、mtrace
1、介绍
  mtrace是包含在GNU C库里一个内存调试工具。mtrace()函数为内存分配函数(malloc,realloc,free)安装hook函数,这些hook函数用于记录内存的分配与释放的跟踪信息,这些跟踪信息可用于发现内存泄露。

  muntrace()函数会使已安装的hook函数失效,所以就不再对内存的分配进行跟踪。当mtrace()被调用时,它会检查环境变量MALLOC_TRACE的值,内存分配信息会记录下该环境变量所指的文件里。

  通常情况下,mtrace()程序执行前调用,而muntrace不用调用,因为有些内存要在程序结束时才会释放。mtrace所产生的跟踪信息是文本文件,但不易于人理解,可通过GNU C库提供的Perl脚本来解释。为了能够得到文件的具体位置出现了内存泄露,程序需要以debug模式编译。

2、使用步骤
  1)main函数所在文件包含头文件的 <mcheck.h>,main函数开头调用mtrace()
  2)以debug模式编译源代码
  3) 设置环境变量MALLOC_TRACE=output_file指定记录跟踪信息的文件路径(实测表明在代码里设置环境变量才有效)
  4)执行可执行程序 ./test, 会生成output_file文件
  5)执行GNU C提供的Perl的脚本: mtrace test output_file
3、实例

  //test.c: 
1 #include <mcheck.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 5 int main(int argc, char *argv[]) 6 { 7 setenv("MALLOC_TRACE","output_file",1); 8 mtrace(); 9 10 for (int j = 0; j < 2; j++) 11 malloc(2); /* Never freed--a memory leak */ 12 13 calloc(2,2); /* Never freed--a memory leak */ 14 exit(EXIT_SUCCESS); 15 }

   执行: gcc -g test.c -o test

           ./test 

           mtrace test output_file 

   检测结果:

- 0x084f8008 Free 5 was never alloc‘d 0xb7617024
- 0x084f8070 Free 6 was never alloc‘d 0xb76cb866
- 0x084f8090 Free 7 was never alloc‘d 0xb76cb86e

Memory not freed:
-----------------
Address Size Caller
0x084f8418 0x2 at /home/zpy/tmp/test.c:10 (discriminator 2)
0x084f8428 0x2 at /home/zpy/tmp/test.c:10 (discriminator 2)
0x084f8438 0x4 at /home/zpy/tmp/test.c:14

     内存泄露的大小及位置都显示出来了。

4、总结:

  mtrace仅仅能检测C语言中通过malloc、realloc等分配的内存,并不能对C++中通过new分配的内存,需要对源代码重新编译才能检测。

 

二、memwatch 

 1、介绍

memwatch是一个内存泄露检测工具,其特征如下:

    • 支持ANSI C
    • 检测多次释放内存,以及错误的释放方式
    • 检测未释放的内存
    • 检测内存buffer的上溢与下溢
    • 检测对野指针的写
    • 部分支持C++(默认disabled)

2、使用方式:

  1)下载memwatch包,解压

  2)在所有需要进行检测的代码源文件中都包含 memwath.h 头文件

    3)重新编译源代码,并指定宏定义MEMWATCH  MEMWATCH_STDIO

  4)执行程序./test 

  5)查看生成的文件memwatch.log内容

3、实例:

//test.c
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include "memwatch.h" 4 int main(int argc, char *argv[]) 5 { 6 for (int j = 0; j < 2; j++) 7 malloc(2); /* Never freed--a memory leak */ 8 9 calloc(2,2); /* Never freed--a memory leak */ 10 exit(EXIT_SUCCESS); 11 }

  编译: gcc -DMEMWATCH -DMW_STDIO  test.c memwatch.c -o test

  运行:./test 

  查看memwatch.log文件:

  1                                                                                                                                                                         
  2 ============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =============
  3 
  4 Started at Sat Apr 16 02:54:55 2016
  5 
  6 Modes: __STDC__ 64-bit mwDWORD==(unsigned long)
  7 mwROUNDALLOC==8 sizeof(mwData)==32 mwDataSize==32
  8 
  9 
 10 Stopped at Sat Apr 16 02:54:55 2016
 11 
 12 unfreed: <3> test.c(9), 4 bytes at 0x92a6260      {00 00 00 00 .. .. .. .. .. .. .. .. .. .. .. .. ....}
 13 unfreed: <2> test.c(7), 2 bytes at 0x92a6228      {FE FE .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..}
 14 unfreed: <1> test.c(7), 2 bytes at 0x92a61f0      {FE FE .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..}
 15 
 16 Memory usage statistics (global):
 17  N)umber of allocations made: 3
 18  L)argest memory usage      : 8
 19  T)otal of all alloc() calls: 8
 20  U)nfreed bytes totals      : 8

 4、总结:

  memwatch能够较好地对C语言中的内存泄露进行检测,对C++ 中new分配的内存不建议采用些工具检测,因为它对C++支持不完善。使用该工具需要重新编译源代码,并需要在所有的源文件中都要包含头文件 "memwatch.h"

三、LeakTracer

 1、介绍

LeakTracer是一个小型的C++内存泄露检测工具。它能够检测如下内存问题:

    • 未释放的内存
    • 对超出所分配内存范围外的overwritten
    • 试图释放并未分配的内存(比如释放garbage pointer以及多次释放)
    • 释放与分配函数的不匹配,如使用new[]分配,而使用delete释放

  在使用LeakTracer时,通过提供的LeakCheck脚本运行你的程序,它使用LD_PRELOAD在你的函数上层进行“重写”。如果你的平台不支持LD_PRELOAD,则需要将LeakTracer.o 对象文件加入到Makefile文件中,然后运行你的应用程序

  LeakTracer利用gdb去输出发生内存泄露所发生的位置,它是通过override operator new和operator delete来实现检测。

2、使用方法:

  1)下载LeakTracer

  2)解压,执行make, 会生成LeakTracer.so

  3)以debug模式编译源代码

  4)通过提供的LeakCheck运行程序:./LeakCheck ./test ,会生成leak.out文件

  5)通过提供的leak-analyze脚本分析结果:./leak-analyze test leak.out (leak-analyze 会加载LeakTracer.so,所以注意路径)

3、实例:

  1 // Small leaky test program                                                                                                                                             
  2 
  3 void foo() {
  4     int *x = new int;
  5 }
  6 
  7 int main() {
  8     int *z = new int[10];
  9     char *q = new char[4];
 10     q[4] = x;                 // MAGIC overrun
 11     // Commenting out should make this abort
 12     // delete q;
 13     foo();
 14     foo();
 15     delete z;
 16     delete z;   // delete value twice
 17 }

  执行:

  g++ -g test.cc -o test 

  ./LeakCheck ./test

  ./leak-analyze test leak.out

  检测结果:

Gathered 4 (3 unique) points of data.
Reading symbols from test...done.
(gdb) 
#-- Alloc: Different allocation schemes
alloc here :0x8048569 is in main() (test.cc:8).
7    int main() {
8        int *z = new int[10];
..free here :0x804859d is in main() (test.cc:16).
16        delete z;   // delete value twice

#-- Leak: counted 2x / total Size: 8
0x804854f is in foo() (test.cc:4).
3    void foo() {
4        int *x = new int;

#-- Leak: counted 1x / total Size: 4
0x8048579 is in main() (test.cc:9).
8        int *z = new int[10];
9        char *q = new char[4];

#-- delete on not allocated memory: counted 1x
0x80485a9 is in main() (test.cc:17).
16        delete z;   // delete value twice
17    }

 

  检测结果反映出发生内存泄露相关的代码,以及所在的文件和行号,非常Nice!

4、总结:

  LeakTracer仅能够检测new/new[] 分配的内存,对于C中malloc等分配的内存无法检测。无需对对源代码进行重新编译。

C/C++内存泄露检测

标签:

原文地址:http://www.cnblogs.com/xey-csu/p/5398857.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!