1. 程式人生 > >Visual Studio內存泄露檢測工具

Visual Studio內存泄露檢測工具

假設 img rep 源文件 amp 語句 size 行數 log

使用簡單介紹

? ? 在敲代碼的過程中。難免會遇到內存泄露的時候。這個時候假設手工查找內存泄露,不說方法沒有通用的,就是真的要自己手工查找也是非常耗時間和精力的。誠然。我們能夠借助一些工具,並且我們還會驚奇地發現這些工具非常實用(比方Intel的內存泄露檢測工具)。可是由於往往這些工具安裝比較麻煩,而我們寫的程序又不是非常大,所以我們也許能夠找個更小巧的方法。微軟就提供了這個方案。我們僅僅須要在程序中加入幾行代碼,就能夠發現內存泄露的問題,然後我們就能夠定位內存泄露了(自己用幾行代碼就能夠實現,奇妙!

)。

那麽怎樣實現了,基本的幾個函數現先列舉一下:_CrtDumpMemoryLeaks,_CrtMemCheckpoint,_CrtMemDifference
  • CrtDumpMemoryLeaks?:當前全部沒有銷毀的對象(沒有delete和free),默認情況下輸出到調試窗體
  • _CrtMemCheckpoint:保存當前全部沒有銷毀的對象的狀態
  • _CrtMemDifference:比較兩個_CrtMemCheckpoint保存的狀態。返回差異值
? 簡單的使用_CrtDumpMemoryLeaks能夠檢測當前沒有釋放的對象。可是假設程序大一點。須要確定某一段程序是否有問題時,就須要後面的兩個參數了。_CrtMemCheckpoint
保存的是_CrtDumpMemoryLeaks的結果。假設我們在一段程序的前後分別保存一個狀態,那麽通過比較這兩個狀態我們就能夠獲知這一段程序是否有內存泄露的問題了。

使用演示樣例

  • 啟用內存泄露調試支持
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <crtdbg.h>
    當中#define 語句將 CRT 堆函數的基礎版本號映射到相應的調試版本號。 假設省略 #define 語句。內存泄漏轉儲將有所簡化。
使用這些語句啟用調試堆函數之後,能夠在某個應用程序退出點之前設置一個對 _CrtDumpMemoryLeaks 的調用,以便在應用程序退出時顯示內存泄漏報告:
_CrtDumpMemoryLeaks();
假設要為程序加入退出點時檢測內存泄露,則能夠通過設置調試選項來設置。而不須要在每一個退出點自己加入函數_CrtDumpMemoryLeaks的調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

默認情況下,輸出的調試信息會在調試窗體。當然,你能夠通過_CrtSetReportMode等來自己定義輸出位置。
	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
	_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR  );

為了使得輸出的內存泄露信息中包括源碼的文件和行信息,還須要定義一些額外的東西,下面是我封裝好的頭文件,在每一個須要檢測內存泄露的文件裏包括該頭文件就可以:
#ifndef __MEM_LEAN_DETECT_H__
#define __MEM_LEAN_DETECT_H__

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define new new( _CLIENT_BLOCK, __FILE__, __LINE__)

#endif
當中 #define _CRTDBG_MAP_ALLOC 語句將 CRT 堆函數的基版本號映射到相應的“Debug”版本號。

並不是絕對須要該語句,但假設沒有該語句,內存泄漏轉儲包括的實用信息將較少。

而 #define new 利用了在源碼中獲代替碼所在文件及行數的方法用以輸出內存泄露源所在的代碼位置。

  • 比較內存泄露狀態
定位內存泄漏的還有一種技術涉及在關鍵點相應用程序的內存狀態拍快照。

若要為應用程序中給定點的內存狀態拍快照,創建 _CrtMemState 結構。將它傳遞給 _CrtMemCheckpoint 函數:

_CrtMemState s1;
_CrtMemCheckpoint( &s1 );
_CrtMemCheckpoint 會將當前內存狀態填充在該結構中。
假設要查看輸出 _CrtMemState 結構的內容。可使用_ CrtMemDumpStatistics 函數:
_CrtMemDumpStatistics( &s1 );

//_ CrtMemDumpStatistics 輸出內存狀態轉儲,例如以下所看到的:
// 0 bytes in 0 Free Blocks.
// 0 bytes in 0 Normal Blocks.
// 3071 bytes in 16 CRT Blocks.
// 0 bytes in 0 Ignore Blocks.
// 0 bytes in 0 Client Blocks.
// Largest number used: 3071 bytes.
// Total allocations: 3764 bytes.

若要確定在某個代碼部分中是否發生了內存泄漏,能夠對這部分之前和之後的內存狀態拍快照,然後使用 _ CrtMemDifference 比較兩個狀態:

_CrtMemCheckpoint( &s1 );
// memory allocations take place here
_CrtMemCheckpoint( &s2 );

if ( _CrtMemDifference( &s3, &s1, &s2) )
{
	_CrtMemDumpStatistics( &s3 );
}
_CrtMemDifference比較內存狀態 s1 和 s2,在 (s3) 中返回結果,即 s1 與 s2 的差異。
尋找內存泄漏的一個方法是,首先在應用程序的開頭和結尾部分放置 _CrtMemCheckpoint 調用,然後使用 _CrtMemDifference 比較兩個結果。 假設 _CrtMemDifference 顯示有內存泄漏。通過加入很多其它 _CrtMemCheckpoint 調用來使用二進制搜索劃分程序,直至找到泄漏源。

  • 貼幾張自己使用的結果圖

技術分享圖片

默認輸出的結果

技術分享圖片

輸出代碼信息的結果(註意源文件名稱和行號)

技術分享圖片

把內存泄露檢測結果自己定義輸出到屏幕


Visual Studio內存泄露檢測工具