Chinaunix首页 | 论坛 | 博客
  • 博客访问: 337784
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: C/C++

2012-11-11 21:18:28

内存泄漏排查
一下本人只是简单的介绍一个实用, 如果读者很感兴趣, 可以查阅msdn自己去深入调查相关的API和原理.
API 介绍
1. 马上打印泄漏信息:_CrtDumpMemoryLeaks();
一般用于局部跟踪内存泄漏问题,使用的方法很简单,你怀疑在某一个时刻有内存泄漏了,就执行这个函数调用,然后在 vs 调试器的 "output" 窗口会马上会打印出当前所有没有释放的内存的申请明细(包括文件名,行号, 第几次内存分配)。
双击就可以定位到源文件 内存申请的地方, 很方便.

2. 程序结束之前打印泄漏信息:
一般用于全局的内存泄漏问题,在程序刚开始的时候就可以用起来。
使用方法也很简单,执行下面两个语句, 先初始化, 然后设置在第几次的内存分配停住.

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(long); // 设置在第几次内存分配的时候程序暂停执行,并回复现场

环境的设置
1. 每一个MFC生成的类都会有下面的语句
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define DEBUG_NEW new(THIS_FILE, __LINE__) 
#define new DEBUG_NEW
#endif
有了这些定义打印泄漏信息的时候就能准备的定位到文件名和行号,双击就能定位过去。

2. 非MFC也可以利用现有的VC库来实现这个功能,同样是在new上面花功夫,如下:
#ifdef _DEBUG
#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
有了这几行代码,功能上面和MFC就一样了。

3. 获得具体导致内存泄漏的那一份内存分配操作的现场。
获得的静态信息里面,在文件名和行号后面还有一个数字,就是代表具体第几次内存分配 (这里是197)。
所以,我们调用_CrtSetBreakAlloc(197);程序就会在这一次内存分配的时候停下来,这样我们就获得了现场。
Detected memory leaks!
Dumping objects ->
d:\src-project\basictest - 副本\basictest\main.cpp(48) : {197} normal block at 0x002D9488, 128 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.

样例代码:
  1. #ifdef _DEBUG
  2. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) // 方便调试输出文件行号信息
  3. #endif
  4. void MemoryTest() {
  5.     _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); // 全局设置, 程序退出的时候可以看见内存泄漏.
  6.     _CrtSetBreakAlloc(55); // 第55次内存分配的时候停止.
  7.     int *p = new int(10); // 分配内存
  8.     _CrtDumpMemoryLeaks(); // 检查当前有哪些内存没有释放.
  9. }
阅读(3500) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~