VC++ 内存泄露与检测的一种方法

    本文介绍,当VC++或者MFC程序,出现内存泄露时,如何快速定位的方法,这种方法有一定的局限性,在注意事项中会给出的。

MFC程序

    当MFC程序出现内存泄露时,退出程序时的VS调试输出窗口,一般会有如下显示:

image

   上面显示了在程序的哪个文件的哪行语句,发生了内存泄露,其中:

   {345}: 表示 内存分配编号

   normal block:表示 内存块类型,有普通块(普通程序分配)、客户端块(分配基于CObject的内存)和CRT块(库函数内部分配)这几种类型

   0x0074A030:以16进制形式输出的内存位置

   40 bytes long: 以字节为单位的内存块大小

   Data<   >CD CD ..:内存块前16个字节的内容,16进制表示。

      定位内存泄露位置,可以双击泄露信息,也可以在输出窗口 按F4键,跳转到 出错行。

 

普通VC++程序

    在普通VC++程序中,要类似MFC中内存检测的效果,需要做如下操作。

    1.  在头文件中,添加  #include <ctrdbg.h>

    2.  在程序入口最开始处,添加 下面两句话即可

        _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );    //设置调试堆函数跟踪分配的方式
        //_CrtSetBreakAlloc();     //这句话,在确实有内存泄露的情况下,给 内存分配编号

    3. 按F5,运行程序,等待程序退出后,在输出窗口可以看到下面的情况:

      image

     如图所示,程序有两处内存泄露地方,分配编号为 476 和 475,此时,给_CrtSetBreakAlloc()函数传入476参数,再次运行程序,在退出时,会弹出如下窗口:

     image

点击 中断  跳到,_CrtSetBreakAlloc()中断的地方,然后在程序中,通过查看调用堆栈,就可以看到应用程序的哪一次new操作没有执行delete操作。

在中断的同时,也可以从控制台中,看到整个程序析构的顺序,如下图所示:

image

 

注意事项

1. 当程序确认没有内存泄露时,不可以调用_CrtSetBreakAlloc(475),因为,这样会在指定内存分配次数发生时,强制中断程序。

2. 这种检测内存分配的方式,要求,程序在执行过程中,是可还原的(多次执行过程的内存分配顺序不会发送变化),这个假设,在多数情况下是成立的,不过,在多线程执行的环境下,有时候难以保证。

3. 对于普通C程序,上述检测方法也是成立的,只不过new换成了malloc,delete换成了free

4. 比如 int *p = new int[4]; delete p; 这种方式的泄露,上述方法是检测不出来,此时,需要cppcheck等更有力的工具来检查。

 

参考链接:C++调试堆

原文地址:https://www.cnblogs.com/cherishui/p/4637118.html