最快速度找到内存泄漏

内存管理C++程序的痛。我的《内存管理革系列》就是试图讨论有效的内存管理方式,以杜(或减少)内存泄漏,减C++程序担。

篇短文我想个方式,讨论一下如何以最快的速度找到内存泄漏。

是否存在内存泄漏

知道,MFC程序如果检测到存在内存泄漏,退出程序的候会在调试窗口提醒内存泄漏。例如:

class CMyApp : public CWinApp

{

public:

   BOOL InitApplication()

   {

       int* leak = new int[10];

       return TRUE;

   }

};

生的内存泄漏告大体如下:

Detected memory leaks!

Dumping objects ->

c:/work/test.cpp(186) : {52} normal block at 0×003C4410, 40 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

挺好。问题是,如果我不喜MFC,那么难道就没有法?或者自己做?

呵呵,不需要。MFC也没有自己做。内存泄漏检测的工作是VC++C运行做的。也就是,只要你是VC++程序,都可以很方便地检测内存泄漏。我们还例:

#include <crtdbg.h>

 

inline void EnableMemLeakCheck()

{

   _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

}

 

void main()

{

   EnableMemLeakCheck();

   int* leak = new int[10];

}

运行(提醒:不要按Ctrl+F5,按F5),你将发现生的内存泄漏告与MFC似,但有细节不同,如下:

Detected memory leaks!

Dumping objects ->

{52} normal block at 0×003C4410, 40 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

呢?看下面。

定位内存泄漏由于哪一句引起的

你已经发现程序存在内存泄漏。在的问题是,我要找泄漏的根源。

一般我首先确定内存泄漏是由于哪一句引起。在MFC中,一点很容易。你双内存泄漏告的文字,或者在Debug窗口中按F4IDE就帮你定位到申请该内存的地方。于上例,也就是一句:

int* leak = new int[10];

多多少少你分析内存泄漏有点帮助。特地,如果new仅对应一条delete(或者你把delete漏写),将很快可以确认问题的症

前面已看到,不使用MFC候,生成的内存泄漏告与MFC不同,而且你立刻发现F4不灵。那么难MFC做了什手脚?

不是,我来模MFC做的事情。看下例:

inline void EnableMemLeakCheck()

{

   _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

}

 

#ifdef _DEBUG

#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)

#endif

 

void main()

{

   EnableMemLeakCheck();

   int* leak = new int[10];

}

再运行例,你惊喜地发现在内存泄漏告和MFC没有任何分了。

快速找到内存泄漏

确定了内存泄漏生在哪一行,有候并不足。特是同一个new对应有多处释放的情形。在实际的工程中,以下两情况很典型:

· 象的地方是一个工厂(ClassFactory)模式。很多甚至全部类实例由同一个new建。于此,定位到了new象的所在行基本没有多大帮助。

· COM象。我知道COM象采用Reference Count维护生命周期。也就是new的地方只有一个,但是Release的地方很多,你要一个个排除。

,有什法,可以迅速定位内存泄漏?

答:有。

在内存泄漏情况复杂候,你可以用以下方法定位内存泄漏。是我个人认为通用的内存泄漏追踪方法中最有效的手段。

再回看看crtdbg生成的内存泄漏告:

Detected memory leaks!

Dumping objects ->

c:/work/test.cpp(186) : {52} normal block at 0×003C4410, 40 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

除了内存泄漏的内存分配句所在的文件名、行号,我注意到有一个比陌生的信息:{52}个整数代表了什意思呢?

,它代表了第几次内存分配操作。个例子,{52}代表了第52次内存分配操作生了泄漏。你可能要,我只new一次,怎会是第52次?很容易理解,其他的内存申操作在C的初始化用的:)

有没有可能,我们让程序运行到第52次内存分配操作的候,自停下来,调试?所幸,crtdbg提供了这样的函数:即 long _CrtSetBreakAlloc(long nAllocID)加上它:

inline void EnableMemLeakCheck()

{

   _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

}

 

#ifdef _DEBUG

#define new   new(_NORMAL_BLOCK, __FILE__, __LINE__)

#endif

 

void main()

{

   EnableMemLeakCheck();

   _CrtSetBreakAlloc(52);

   int* leak = new int[10];

}

发现,程序运行到 int* leak = new int[10]; 一句,自停下来调试细细体会一下,你可以发现这种方式你得的信息比在程序退出时获得文件名及行号有价得多。为报告泄漏文件名及行号,你得的只是静的信息,然而_CrtSetBreakAlloc是把整个现场,你可以通过对函数分析(我发现很多人不习惯看函数,如果你属于这种情况,我烈推荐你去,因它太重要了)以及其他在线调试技巧,来分析生内存泄漏的原因。通常情况下,这种分析方法可以在 5内找到肇事者。

当然,_CrtSetBreakAlloc要求你的程序程是可原的(多次程的内存分配序不会化)。个假在多数情况下成立。不,在多线程的情况下,一点有时难以保

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值