现在的位置: 首页 > 综合 > 正文

Linux平台下如何检测、调试C/C++程序内存泄漏

2013年02月07日 ⁄ 综合 ⁄ 共 2609字 ⁄ 字号 评论关闭

1. 如何发现内存泄漏

  1. ps -aux

2. 静态分析

  1. **2.1 手动检测**
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. int LeakTest(char * Para)
  6. {
  7.     if(NULL==Para)
  8.     {
  9.         //local_log("LeakTest Func: empty parameter\n");
  10.         return -1;
  11.     }
  12.     char * Logmsg = new char[128];
  13.     if(NULL == Logmsg)
  14.     {
  15.         //
  16.         local_log("memeory allocation failed\n");
  17.         return -2;
  18.     }
  19.     sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);
  20.     local_log(Logmsg); return 0;
  21. }
  22. int main(int argc,char **argv )
  23. {
  24.     char szInit [] = "testcase1";
  25.     LeakTest(szInit);
  26.     return 0;
  27. }
  28. **2.2 静态代码分析工具**
  29. 代码静态扫描和分析的工具比较多,比如 splint, PC-LINT, BEAM 等。因为 BEAM 支持的平台比较多,这以 BEAM 为例,做个简单介绍,其它有类似的处理过程。

BEAM 可以检测四类问题: 没有初始化的变量;废弃的空指针;内存泄漏;冗余计算。而且支持的平台比较多。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int *p;
  5. void foo(int a)
  6. {
  7.     int b, c; b = 0;
  8.     if(!p)
  9.         c = 1;
  10.     if(c > a)
  11.         c += p[1];
  12. }
  13. int LeakTest(char * Para)
  14. {
  15.     char * Logmsg = new char[128];
  16.     if((Para==NULL)||(Logmsg == NULL))
  17.         return -1;
  18.     sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);
  19.     return 0;
  20. }
  21. int main(int argc,char **argv )
  22. {
  23.     char szInit [] = "testcase1";
  24.     LeakTest(szInit);
  25.     return 0;
  26. }
  27. **2.3 内嵌程序**

可以重载内存分配和释放函数 new 和 delete,然后编写程序定期统计内存的分配和释放,从中找出可能的内存泄漏。或者调用系统函数定期监视程序堆的大小,关键要确定堆的增长是泄漏而不是合理的内存使用。这类方法比较复杂,在这就不给出详细例子了。

3. 动态运行检测
实时检测工具主要有 valgrind, Rational purify 等。

3.1 Valgrind
valgrind 是帮助程序员寻找程序里的 bug 和改进程序性能的工具。程序通过 valgrind 运行时,valgrind 收集各种有用的信息,通过这些信息可以找到程序中潜在的 bug 和性能瓶颈。
Valgrind 现在提供多个工具,其中最重要的是 Memcheck,Cachegrind,Massif 和 Callgrind。Valgrind 是在 Linux 系统下开发应用程序时用于调试内存问题的工具。它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。其中的 memecheck 工具可以用来寻找 c、c++ 程序中内存管理的错误。可以检查出下列几种内存操作上的错误:

  • 读写已经释放的内存
  • 读写内存块越界(从前或者从后)
  • 使用还未初始化的变量
  • 将无意义的参数传递给系统调用
  • 内存泄漏
  • 请输入列表文字

3.2 Rational purify
Rational Purify 主要针对软件开发过程中难于发现的内存错误、运行时错误。在软件开发过程中自动地发现错误,准确地定位错误,提供完备的错误信息,从而减少了调试时间。同时也是市场上唯一支持多种平台的类似工具,并且可以和很多主流开发工具集成。Purify 可以检查应用的每一个模块,甚至可以查出复杂的多线程或进程应用中的错误。另外不仅可以检查 C/C++,还可以对 Java 或 .NET 中的内存泄漏问题给出报告。

示例代码

  1. #include <unistd.h>
  2. char * Logmsg;
  3. int LeakTest(char * Para)
  4. {
  5.     if(NULL==Para)
  6.     { //
  7.         local_log("LeakTest Func: empty parameter\n");
  8.         return -1;
  9.     }
  10.     Logmsg = new char[128];
  11.     for (int i = 0 ; i < 128; i++)
  12.         Logmsg[i] = i%64;
  13.     if(NULL == Logmsg)
  14.     { //
  15.         local_log("memeory allocation failed\n");
  16.         return -2;
  17.     }
  18.     sprintf(Logmsg,"LeakTest routine exit: '%s'.\n", Para);
  19.     //
  20.     local_log(Logmsg);
  21.     return 0;
  22. }
  23. int main(int argc,char **argv )
  24. {
  25.     char szInit [] = "testcase1";
  26.     int i;
  27.     LeakTest(szInit);
  28.     for (i=0; i < 2; i++)
  29.     { if(i%200 == 0)
  30.     LeakTest(szInit);
  31.     sleep(1);
  32.     }
  33.     return 0;
  34. }

1."内存泄露"包括堆内存泄露、栈内存泄露。根据内存的类型,又分为:内存申请、释放,句柄的打开与关闭问题。
2.容易忽视的是栈上的内存泄露,严格来讲是申请的内存超过线程栈空间大小(默认为1MB)。栈上的内存(即局部变量)是不需要释放的,函数返回自动出栈(释放)。若某时刻超过线程栈空间大小,造成其它使用栈的地方不能正常工作(如函数调用、SEH等),会使程序崩溃(驱动的话会蓝屏)。所以申请局部变量内存时,不要太大。
3.堆内存申请、释放。主要是要注意申请的地方要记得释放,以及申请、释放函数要配对使用。比如malloc和free、new和delete、BSTR的SysAllocString和SysFreeString。
4.还有一个地方也往往被忽略,"句柄的打开与关闭问题"。这个当积累到一定数量,是

抱歉!评论已关闭.