使用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.