`

VC下内存泄漏的检测方法

阅读更多
用MFC研发的应用程式,在DEBUG版模式下编译后,都会自动加入内存泄漏的检测代码。在程式结束后,假如发生了内存泄漏,在Debug窗口中会显示出任何发生泄漏的内存块的信息,以下两行显示了一块被泄漏的内存块的信息:

E:\TestMemLeak\TestDlg.cpp(70) : {59} normal block at 0x00881710, 200 bytes long.

Data: <abcdefghijklmnop> 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70

  第一行显示该内存块由TestDlg.cpp文档,第70行代码分配,地址在0x00881710,大小为200字节,{59}是指调用内存分配函数的Request Order,关于他的周详信息能够参见MSDN中_CrtSetBreakAlloc()的帮助。第二行显示该内存块前16个字节的内容,尖括号内是以ASCII方式显示,接着的是以16进制方式显示。

  一般大家都误以为这些内存泄漏的检测功能是由MFC提供的,其实不然。MFC只是封装和利用了MS C-Runtime Library的Debug Function。非MFC程式也能够利用MS C-Runtime Library的Debug Function加入内存泄漏的检测功能。MS C-Runtime Library在实现malloc/free,strdup等函数时已内建了内存泄漏的检测功能。

  注意观察一下由MFC Application Wizard生成的项目,在每一个cpp文档的头部都有这样一段宏定义:


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


  有了这样的定义,在编译DEBUG版时,出现在这个cpp文档中的任何new都被替换成DEBUG_NEW了。那么DEBUG_NEW是什么呢?DEBUG_NEW也是个宏,以下摘自afx.h,1632行


#define DEBUG_NEW new(THIS_FILE, __LINE__)


  所以假如有这样一行代码:


char* p = new char[200];


  经过宏替换就变成了:


char* p = new( THIS_FILE, __LINE__)char[200];


  根据C++的标准,对于以上的new的使用方法,编译器会去找这样定义的operator new:


void* operator new(size_t, LPCSTR, int)


  我们在afxmem.cpp 63行找到了一个这样的operator new 的实现


void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
 return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
}

void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
{
 …
 pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine);
 if (pResult != NULL)
  return pResult;
 …
}


  第二个operator new函数比较长,为了简单期间,我只摘录了部分。很显然最后的内存分配还是通过_malloc_dbg函数实现的,这个函数属于MS C-Runtime Library 的Debug Function。这个函数不但需要传入内存的大小,另外更有文档名和行号两个参数。文档名和行号就是用来记录此次分配是由哪一段代码造成的。假如这块内存在程式结束之前没有被释放,那么这些信息就会输出到Debug窗口里。

  这里顺便提一下THIS_FILE,__FILE和__LINE__。__FILE__和__LINE__都是编译器定义的宏。当碰到__FILE__时,编译器会把__FILE__替换成一个字符串,这个字符串就是当前在编译的文档的路径名。当碰到__LINE__时,编译器会把__LINE__替换成一个数字,这个数字就是当前这行代码的行号。在DEBUG_NEW的定义中没有直接使用__FILE__,而是用了THIS_FILE,其目的是为了减小目标文档的大小。假设在某个cpp文档中有100处使用了new,假如直接使用__FILE__,那编译器会产生100个常量字符串,这100个字符串都是飧?/SPAN>cpp文档的路径名,显然十分冗余。假如使用THIS_FILE,编译器只会产生一个常量字符串,那100处new的调用使用的都是指向常量字符串的指针。

  再次观察一下由MFC Application Wizard生成的项目,我们会发现在cpp文档中只对new做了映射,假如您在程式中直接使用malloc函数分配内存,调用malloc的文档名和行号是不会被记录下来的。假如这块内存发生了泄漏,MS C-Runtime Library仍然能检测到,但是当输出这块内存块的信息,不会包含分配他的的文档名和行号。

  要在非MFC程式中打开内存泄漏的检测功能很容易,您只要在程式的入口处加入以下几行代码:


int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );

tmpFlag |= _CRTDBG_LEAK_CHECK_DF;

_CrtSetDbgFlag( tmpFlag );


  这样,在程式结束的时候,也就是winmain,main或dllmain函数返回之后,假如更有内存块没有释放,他们的信息会被打印到Debug窗口里。

  假如您试着创建了一个非MFC应用程式,而且在程式的入口处加入了以上代码,并且故意在程式中不释放某些内存块,您会在Debug窗口里看到以下的信息:


{47} normal block at 0x00C91C90, 200 bytes long.

Data: < > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F


  内存泄漏的确检测到了,但是和上面MFC程式的例子相比,缺少了文档名和行号。对于一个比较大的程式,没有这些信息,解决问题将变得十分困难。

  为了能够知道泄漏的内存块是在哪里分配的,您需要实现类似MFC的映射功能,把new,maolloc等函数映射到_malloc_dbg函数上

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sailing0123/archive/2008/11/04/3212895.aspx
分享到:
评论

相关推荐

    VC6 内存泄漏检测

    利用VC++6.0撰写内存泄漏检测的方法

    VC下内存泄露检测与CListCtrl使用技巧

    VC下内存泄露检测与CListCtrl使用技巧;VC下内存泄露检测与CListCtrl使用技巧

    vc中内存泄露的检测方法

    内存泄露是编程时候经常遇到的问题,但是这个问题有时候很隐蔽,不易被发现和检测出来,这个文档就是在vc和vs编程工具下,教同学们如何检测内存泄露的。

    VC内存泄露检测以及定位方法

    VC内存泄露检测以及定位方法

    VC下内存泄漏的检测方法.pdf

    帮助解决VC++程序的内存泄露,提高程序的质量

    BoundsChecker6.5vc6.0内存泄漏检测

    用 vc6.0编译器开发程序时,出现内存泄漏,该工具可快速侦测到泄漏位置,方便快捷

    VC内存泄露检测工具 Visual Leak Detector

    VC内存泄露检测工具 Visual Leak Detector 介绍

    VC使用CRT调试功能来检测内存泄漏.rar_VC 内存_VC 调试_Vc_内存泄漏

    VC使用CRT调试功能来检测内存泄漏 C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话。在 C/C++ 应用程序...

    VC内存泄漏检测原理及源码

    C++内存泄漏检测原理+实例源码下载,是一个跨平台的C++ 内存泄漏检测器的源程序,一个主要缺陷是不支持多线程。分配内存时不进行文件名复制,而只是保存其指针;效率较高(编译debug_new.cpp 时有效;参见文件中的...

    vc内存泄露检测

    C/C++ 编程语言的最强大功能之一便是其动态... 幸运的是,Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法。下面请和我一起分享收获——如何使用 CRT 调试功能来检测内存泄漏?

    VC内存泄漏检测及TRACE方法

    用VC创建非MFC工程(例如不支持MFC的DLL),不支持MFC下经常用的TRACE、VERIFY等调试手段,对于内存泄漏也没有检测。其实C++本身是支持这些功能的,只是使用方式与MFC稍有区别。 将压缩包里面的文件解压到VC工程下,...

    VC内存检测工具

    相比较其它的内存泄露检测工具,它在检测到内存泄漏的同时,还具有如下特点: 1、 可以得到内存泄漏点的调用堆栈,如果可以的话,还可以得到其所在文件及行号; 2、 可以得到泄露内存的完整数据; 3、 可以设置内存...

    vc++内存泄漏检测工具

    一款很好用 的内存泄漏检测工具,对初学者是个很好的学习机会

    linux下检测内存泄漏

    在 windows 下使用 VC 编程时,我们通常需要 DEBUG 模式下运行程序,而后...下文将简述 C++ 中的 new 和 delete 的基本原理,并讲述了内存检测子系统的实现原理、实现中的技巧,并对内存泄漏检测的高级话题进行了讨论。

    vc内存泄露检测类

    使用时将要检测的工程中cpp包含文件列表后添加宏定义: #ifdef _DEBUG #define new CLIENT_NEW #endif //CLIENT_NEW

    内存泄露检测

    用于vc编程等内存是否泄露的检测工具!有需要的可以下载试试

    VC内存泄漏检测工具-Visual Leak Detector

    非常实用的vc工具,用于检测程序是否存在内存泄漏!

    VC使用CRT调试功能来检测内存泄漏

    Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,本文件教你如何使用 CRT 调试功能来检测内存泄漏.

    VC内存泄露检查.rar

    用于检测DLL这类VC工具不能检测的内存泄漏库。 使用方法: 1,在VC 工具--&gt;选项--&gt;VC目录里将头文件和库文件路径选入 2,INCLUDE头文件即可。

    Linux-operator-new-delete.rar_Operator Down_VC debug技巧_内存泄漏

    简述 C++ 中的 new 和 delete 的基本原理,并讲述了内存检测子系统的实现原理、实现中的技巧,并对内存泄漏检测的高级话题进行了讨论。解决了本人在内存泄露很多多问题(我也是down的别人的),觉得非常好,所以给...

Global site tag (gtag.js) - Google Analytics