使用vs的内存检测有如下几种方法。html
在debug模式下以F5运行:windows
方法一:函数
#define CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> //在入口函数中包含 _CrtDumpMemoryLeaks(); //便可检测到内存泄露 //以以下测试函数为例: int main() { char* pChars = new char[10]; _CrtDumpMemoryLeaks(); return 0; }
F5运行输出窗口会获得:测试
Detected memory leaks!
Dumping objects ->
{58} normal block at 0x00341A38, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
Object dump complete.spa
以上方法没有输出.net
注意:
1.在VS2010下测试的时候,发现_CrtDumpMemoryLeaks();这句必须放在函数结束处,放在主函数入口处输出窗口不会输出内存泄露信息
2.{}中的数字指明这块内存是程序中总计第几个被申请的,这种方法没有行号和其余信息输出。咱们能够定义:debug
#ifdef _DEBUG #define New new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif #define CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> //在入口函数中包含 _CrtDumpMemoryLeaks(); //便可检测到内存泄露 //以以下测试函数为例: int main() { char* pChars = New char[10]; _CrtDumpMemoryLeaks(); return 0; }
Detected memory leaks!
Dumping objects ->
e:\vs2005\stltest\stltest\test.cpp(14) : {58} normal block at 0x00591A38, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
Object dump complete.code
方法二: orm
#define CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> //在入口函数中包含 _CrtDumpMemoryLeaks(); //便可检测到内存泄露 //定义函数: inline void EnableMemLeakCheck() { _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); } //该函数能够放在主函数的任意位置,都能正确的触发内存泄露输出 //以以下测试函数为例: int main() { EnableMemLeakCheck(); char* pChars = new char[10]; //_CrtDumpMemoryLeaks(); return 0; }
Detected memory leaks!
Dumping objects ->
{58} normal block at 0x004F1A38, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
Object dump complete.
方法三:直接定位指定内存块错误的代码行
单肯定了内存泄漏发生在哪一行,有时候并不足够。特别是同一个new对应有多处释放的情形。在实际的工程中,如下两种状况很典型:
建立对象的地方是一个类工厂(ClassFactory)模式。不少甚至所有类实例由同一个new建立。对于此,定位到了new出对象的所在行基本没有多大帮助。
COM对象。咱们知道COM对象采用Reference Count维护生命周期。也就是说,对象new的地方只有一个,可是Release的地方不少,你要一个个排除。
那么,有什么好办法,能够迅速定位内存泄漏?
答:有。
在内存泄漏状况复杂的时候,你能够用如下方法定位内存泄漏。这是我我的认为通用的内存泄漏追踪方法中最有效的手段。
咱们再回头看看crtdbg生成的内存泄漏报告:
Detected memory leaks!
Dumping objects ->
{58} normal block at 0x004F1A38, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
Object dump complete.
除了产生该内存泄漏的内存分配语句所在的文件名、行号为,咱们注意到有一个比较陌生的信息:{58}。这个整数值表明了什么意思呢?
其实,它表明了第几回内存分配操做。象这个例子,{58}表明了第58次内存分配操做发生了泄漏。你可能要说,我只new过一次,怎么会是第58次?这很容易理解,其余的内存申请操做在C的初始化过程调用的呗。:)
有没有可能,咱们让程序运行到第58次内存分配操做的时候,自动停下来,进入调试状态?所幸,crtdbg确实提供了这样的函数:即 long _CrtSetBreakAlloc(long nAllocID)。咱们加上它:
1 #define CRTDBG_MAP_ALLOC 2 #include <stdlib.h> 3 #include <crtdbg.h> 4 5 int main() 6 { 7 _CrtSetBreakAlloc(58); 8 char* pChars = new char[10]; 9 _CrtDumpMemoryLeaks(); 10 return 0; 11 }
你发现,程序运行到 char* pChars = new char[10];一句时,自动停下来进入调试状态。细细体会一下,你能够发现,这种方式你得到的信息远比在程序退出时得到文件名及行号有价值得多。由于报告泄漏文件名及行号,你得到的只是静态的信息,然而_CrtSetBreakAlloc则是把整个现场恢复,你能够经过对函数调用栈分析(我发现不少人不习惯看函数调用栈,若是你属于这种状况,我强烈推荐你去补上这一课,由于它过重要了)以及其余在线调试技巧,来分析产生内存泄漏的缘由。一般状况下,这种分析方法能够在5分钟内找到肇事者。
PS:在VS2010下使用这两种方法,宏和头文件不用包含也能够正确运行:
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
非MFC程序能够用如下方法检测内存泄露:
1.程序开始包含以下定义:
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif // _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif // _DEBUG
2.程序中添加下面的函数:
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
Debug版本程序运行结束后若有内存泄漏,输出窗口中会显示相似信息:
Detected memory leaks!
Dumping objects ->
g:\programs\test\test.cpp(16) : {51} client block at 0x00385C58, subtype 0, 4 bytes long.
Data: < > CD CD CD CD
Object dump complete.
MFC程序内存泄漏检测方法:
1.在 CMyApp 中添加以下三个 CMemoryState 类的成员变量:
#ifdef _DEBUG
protected:
CMemoryState m_msOld, m_msNew, m_msDiff;
#endif // _DEBUG
2.在 CMyApp::InitInstance() 中添加以下代码:
#ifdef _DEBUG
m_msOld.Checkpoint();
#endif // _DEBUG
3.在 CMyApp::ExitInstance() 中添加以下代码:
#ifdef _DEBUG
m_msNew.Checkpoint();
if (m_msDiff.Difference(m_msOld, m_msNew))
{
afxDump<<"\nMemory Leaked :\n";
m_msDiff.DumpStatistics();
afxDump<<"Dump Complete !\n\n";
}
#endif // _DEBUG
Debug版本程序运行结束后若有内存泄漏,输出窗口中会显示相似信息:
Memory Leaked :
0 bytes in 0 Free Blocks.
8 bytes in 1 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 8825 bytes.
Total allocations: 47506 bytes.
Dump Complete !
Detected memory leaks!
Dumping objects ->
g:\programs\chat\chatdlg.cpp(120) : {118} normal block at 0x00D98150, 8 bytes long.
Data: < > A8 7F D9 00 01 00 00 00
Object dump complete.