如何定位c++内存泄露

来源:互联网 发布:stc12单片机选型 编辑:程序博客网 时间:2024/06/05 04:24

在进行C++开发时,如果在windows平台上,使用MFC,则可以自动检测内存泄露,如果是win32或者console程序,不使用MFC,则需要自己进行处理。

下面是在总结的一些方法,均来自网上,也经历了实际检验,在此备份。

 

 

1.  利用 KDetectMemoryLeak.h来完成类似MFC重定义NEW宏的效果。可以完成泄露点的输出。

在代码的最后,采用_CrtDumpMemoryLeaks();

具体可以参见《VS2008内存泄露检测》文档,作者写的很清楚,在此谢谢。

 

KDetectMemoryLeak.h 源码:

#pragma once

#ifdef _DEBUG

#define DEBUG_CLIENTBLOCK    new( _CLIENT_BLOCK, __FILE__,__LINE__)

#else

#define DEBUG_CLIENTBLOCK

#endif

#define _CRTDBG_MAP_ALLOC

#include <stdlib.h>

#include <crtdbg.h>

#ifdef _DEBUG

#define new DEBUG_CLIENTBLOCK

#endif

 

 

2.  对于无法定位到具体源代码的泄露,可以通过分析dump出来的信息来定位。

特别是在DLL库中,经常会出现这种情况。

比如:

{152} normal block at 0x01078320, 12 bytes long. 
Data: 08 79 65 00 48 82 07 01 00 00 00 00 
{151} normal block at 0x010782C0, 36 bytes long. 
Data: CD CD CD CD CD CD CD CD 00 00 00 00 00 00 0000 
{150} normal block at 0x01078248, 56 bytes long. 
Data: F4 77 65 00 00 00 00 00 68 71 07 01 90 3A 0910 

 

《软件调试》的702页介绍了堆块转储的细节,取其中的一个堆块为例: 
{137} normal block at 0x01073790, 8 bytes long. 
Data: <H7> 48 37 07 01 CD CD CD CD 
137是堆块的分配序号,堆块的类型为普通堆块,位置为0x01073790,用户区长度为8字节。 
Data后为用户数据区的前16字节,因为这个数据区只有8字节,所以即所有8字节。<H7>是这8字节的ASCII码显示(其它6字节为不可显示的ASCII码)。其中的CD CD CDCD 是CRT在分配堆块时自动填充的固定内容(《软件调试》P696)。这说明这8个字节的堆块,应用程序使用过前4个字节,后四个字节没有使用过。 

 

对于这样的内存泄漏,有很多种办法,你首先可以试一下23.13.1节介绍的内存分配序号断点,也就是重新运行程序,在尽可能早的时候(比如入口),设置序号断点(将_crtBreakAlloc变量设置为要中断的序号,比如137),让CRT分配到指定的内存块时中断。中断下来后,可以根据栈回溯判断是哪个模块在分配内存,记录后,再退出程序,如果这个堆块仍出现在转储列表中,那么刚才那个模块便值得怀疑了。 

如果你有被怀疑的模块源代码,那么可以使用23.15.3节介绍的方法让堆块转储信息中包含源程序的文件名和行号,即下面的样子: 
C:\dig\dbg\author\code\chap23\MemLeak\MemLeak.cpp(22): {74} normal block at 0x00371000, 20 bytes long. 
Data: CD CD CD CD CD CD CD CD CD CD CD CD CD CD CDCD 

 

 

3.可以利用 vld 进行检测。

 

4.还可以利用 boundcheck,purify等工具进行检测。

 

 

原创粉丝点击