在这些函数中用处比较大的,或者说使用率会比较高的函数是,_CrtMemCheckpoint 设置一个内存检查点。这个函数会取得当前内存的运行状态。
_CrtMemDifference 检查两种内存状态的异同。
_CrtMemDumpAllObjectsSince 从程序运行开始,或者从某个内存检查点开始Dump出堆中对象的信息。
还有就是_CrtDumpMemoryLeaks当发生内存溢出的时候Dump出堆中的内存信息。
_CrtDumpMemoryLeaks一般都在有怀疑是内存泄漏的代码后面调用,比如下面的例子:
#include <windows.h> #include <crtdbg.h> void main() { char * pstr; pstr = new char[5]; _CrtDumpMemoryLeaks(); } |
输出:
Detected memory leaks! à提醒你,代码有内存泄漏。 Dumping objects -> {44} normal block at 0x00372DB8,5 bytes long. Data: < > CD CD CD CD CD Object dump complete. |
如果你双击包含行文件名的输出行,指针将会跳到源文件中内存被分配地方的行。
当无法确定那些代码产生了内存泄漏的时候,我们就需要进行内存状态比较。 在可疑的代码段的前后设置内存检查点,比较内存使用是否有可疑的变化。以确定内存是否有泄漏。为此要先定义三个_CrtMemState 对象来保存要比较的内存状态。两个是用来比较,一个用了保存前面两个之间的区别。
_CrtMemState Sh1,Sh2,Sh_Diff; char *pstr1 = new char[100]; _CrtMemCheckPoint(&Sh1); ->设置第一个内存检查点 char *pstr2 = new char[100]; _CrtMemCheckPoint(&Sh2); ->设置第二个内存检查点 _CrtMemDifference(&Sh_Diff, &Sh1,&Sh2); ->检查变化 _CrtMemDumpAllObjectsSince(&Sh_Diff); ->Dump变化 |
如果你的程序中使用了MFC类库,那么内存泄漏的检查方法就相当的简单了。因为Debug版本的MFC本身就提供一部分的内存泄漏检查。 大部分的new 和delete没有配对使用而产生的内存泄漏,MFC都会产生报告。这个主要是因为MFC重载了Debug版本的new 和delete操作符。 并且对前面提到的API函数重新进行了包装。在MFC类库中检查内存泄漏的Class就叫 CMemoryState,它重新包装了了_CrtMemState, _CrtMemCheckPoint, _CrtMemDifference, _CrtMemDumpAllObjectsSince这些函数。并对于其他的函数提供了Afx开头的函数,供MFC程序使用 比如 AfxCheckMemory, AfxDumpMemoryLeaks 这些函数的基本用法同上面提到的差不多。 CMemoryState和相关的函数的定义都在Afx。h这个头文件中。 有个简单的办法可以跟踪到这些函数的申明。 在VC中找到MFC程序代码中下面的代码, 一般都在X.cpp的开头部分。
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif |
把光标移到DEBUG_NEW上面按F12,就可以进入Afx。h中定义这些Class和函数的代码部分。 VC中内存泄漏的常规检查办法主要是上面的两种。当然这两种方法只是针对于Debug版本的Heap的检查。如果Release版本中还有内存泄漏,那么检查起来就麻烦很多了。
4、总结:
实际上Heap的内存泄漏问题是相当的好查的。VC的提供的检查工具也不太少,但是如果是栈出了什么问题,恐怕就麻烦很多了。 栈出问题,一般不会产生内存泄漏,但是你的代码的逻辑上很有可能会有影响。这个是最最痛苦的事情。 编程,就是小心,小心再小心而已。