引用原文地址 : https://msdn.microsoft.com/en-us/library/x98tx3cf.aspx 1. 在program中嚴格按下麵順序include 2. 必須是Debug版的build Q : LiteServer遍Debug可能會遇到一些問題 A : 可以用來驗證 ...
引用原文地址 :
https://msdn.microsoft.com/en-us/library/x98tx3cf.aspx
1. 在program中嚴格按下麵順序include
1 #define _CRTDBG_MAP_ALLOC 2 #include <stdlib.h> 3 #include <crtdbg.h>
2. 必須是Debug版的build
Q : LiteServer遍Debug可能會遇到一些問題
A : 可以用來驗證Memcheck是否有誤報。
可以在對應的地址處下斷點(會頻繁斷在malloc上,需要根據size下條件斷點)
Q : code在Release和Debug版下可能會不一樣,最後可能會出現一個有memory leak一個沒有
3. "#define _CRTDBG_MAP_ALLOC"這個巨集不能省略,否則memory leak的dump會缺少一些細節(如leak的code位置信息)
4. 在app exit前,可以調用這個function列印memory leak report
_CrtDumpMemoryLeaks();
Q : 如果是全局或靜態obj,在exit前其還未釋放,此時report不會造成誤報嗎?
A :不會
5. 如果app有多個exits,你是不需要call _CrtDumpMemoryLeaks()在每個exit位置的。在app開始的位置call下麵這個_CrtSetDbgFlag(),其會自動在每個exit的位置自動call _CrtDumpMemoryLeaks()
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
6. 預設情況下,memory leak的report會在VS Studio Debug窗的Output視窗中,可以用_CrtSetReportMode()將其重定向到其他位置。
7. Report格式
Detected memory leaks! Dumping objects -> c:\users\username\documents\projects\leaktest\leaktest.cpp(20) : {18} //{18} : memory分配序號 normal block at 0x00780E80, 64 bytes long. //64 bytes : block的大小(並不是分配時指定的大小,因為分配的heap由於會添加堆頭堆尾等額外信息,會比分配時指定的size要大) Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD Object dump complete.
Q : 發現即使按照第一條中的定義,也不會輸出memory leak的行信息。
A : 這個crtdbg對new處理不好,其block的地址只會new調用macro的地址,可用如下巨集DBG_NEW來替代new,以列印出對應的行信息
#ifdef _DEBUG #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) // Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the // allocations to be of _CLIENT_BLOCK type #else #define DBG_NEW new #endif
Q : 需要替換所有的源碼,而且第三方庫怎麼辦?
Q : 沒有棧回溯信息,多層調用怎麼查找源頭信息?
A : Debug,在app入口斷下後,在watch視窗輸入"_crtBreakAlloc"(如果"Runtime Library"是"/MD",則還需要添加"{,,ucrtbased.dll}_crtBreakAlloc"),這個值應該是"-1",修改成detect到的memory leak的分配序號(如7中的{18}),當分配該大小的memory時就會斷下來(註意,重跑後的條件要和第一次獲取分配序號的一致)。
另外,在code中也可以直接指定:
_crtBreakAlloc = 18;
or :
_CrtSetBreakAlloc(18);
8. Test
1> code
#include <memory> std ::tr1 ::shared_ptr <int > sp_nTest; void Test () { sp_nTest. reset( new int( 0x88)); //memory leak int* pnTest = new int( 0xCC); void* pMalloc = malloc( sizeof( int)); }
2> result
Detected memory leaks!
Dumping objects ->
d:\codes\vs2010\test\detectmemleak\console\test.cpp(14) : {65} normal block at 0x007B18A8, 4 bytes long.
Data: < > CD CD CD CD
{64} normal block at 0x007B4F90, 4 bytes long.
Data: < > CC 00 00 00 Object dump complete.
紅色部分是new出來的memory leak,可見並不會報出對應的code的行號