記憶體洩漏除錯(1) CRT

2021-08-09 14:59:32 字數 3277 閱讀 1226

記憶體洩漏

c run-time libraries crt

設定斷點

記憶體洩漏的簡單定義是沒有正確的釋放已經分配的記憶體,這在c/c++程式中是乙個很難檢測的bug;一塊較小的記憶體洩漏可能很容易被忽視,但如果記憶體洩漏的現象不斷積累,後果可能導致程式的崩潰,甚至還會影響到其他程式的執行,所以記憶體洩漏的問題值得重視。一方面需要有良好的程式設計習慣,但即使是最優秀的程式設計師也不能保證所寫的**裡沒有記憶體洩漏問題;令一方面使用工具幫助檢測以及定位記憶體洩漏點。

記憶體洩漏問題的除錯一是要檢測是否有記憶體洩漏;二是要定位記憶體洩漏點。

為了檢測記憶體洩漏,在crt中定義了debug heap functions;在需要進行記憶體除錯的**中新增以下宣告(必須按以下順序):

#define _crtdbg_map_alloc

#include

#include

在crtdbg.h中,將c標準的malloc和free庫函式對映到_malloc_dbg和free方法,通過對映的方法來記錄記憶體的分配和釋放情況;一旦引入了上述宣告後,在目標程式的退出位置前通過呼叫 _crtdumpmemoryleaks()就能檢測到是否有記憶體洩漏;但這樣的話只能知道是否有記憶體洩漏,不知道在**發生了記憶體洩漏。

通過以下巨集定義,可以在除錯記憶體洩漏時輸出發生記憶體洩漏的檔案以及在該檔案下的**行數:

#ifdef _debug

#define new

new(_normal_block, __file__, __line__)

#endif

下面是乙個簡單的測試用例:

#define _crtdbg_map_alloc

#include

#include

#ifdef _debug

#define new

new(_normal_block, __file__, __line__)

#endif

int main()

如果在程式中有多個退出位置,在每個退出位置呼叫_crtdumpmemoryleaks();顯然不那麼友好,這時可以通過宣告:

_crtsetdbgflag(_crtdbg_alloc_mem_df | _crtdbg_leak_check_df);

由此可以實現在每個程式退出的位置都會自動呼叫_crtdumpmemoryleaks();

下面是宣告了_crtsetdbgflag的測試用例:

#define _crtdbg_map_alloc

#include

#include

inline void enablememleakcheck()

#ifdef _debug

#define new

new(_normal_block, __file__, __line__)

#endif

int main()

在debug下的輸出:

detected memory leaks!

dumping objects ->

e:\wzcgit\testleak\testleak\test.cpp(12) : normal block at 0x00315f60, 1 bytes long.

data: 61

e:\wzcgit\testleak\testleak\test.cpp(11) : normal block at 0x00315f30, 4 bytes long.

data: < > d2 04 00 00

object dump complete.

執行緒 0xd80 已退出,返回值為 1 (0x1)。

程式「[6636] testleak.exe」已退出,返回值為 1 (0x1)。

簡單剖析輸出結果:

「e:\wzcgit\testleak\testleak\test.cpp(12)」 ——檔名(行號)。

「 normal block at 0x00315f60」——記憶體分配的塊號,我理解的是第67塊記憶體分配時出現記憶體洩漏問題。

「1 bytes long.」——記憶體洩漏的大小。

「data: 61」——記憶體洩漏的資料。

使用crt生成的記憶體洩漏報告中主要會有以下資訊:

the memory allocation number, which is 12 in this example

the block type, which is normal in this example.

the hexadecimal memory location, which is 0x00315f60 in this example.

the size of the block, 1 bytes in this example.

the first 16 bytes of data in the block, in hexadecimal form.

總結:上述方法能檢測出記憶體洩漏並知道在**出現記憶體洩漏,但不知道記憶體洩漏的原因。

在函式入口設定斷點,vs下進入除錯模式,在watch window下name位置輸入_crtbreakalloc,在value處輸入引起記憶體****存塊號,這裡是輸入67,繼續執行後程式會在引發記憶體洩漏的位置(這裡是第67塊記憶體分配位置)中斷。

這時調出函式堆疊(vs:除錯->視窗->呼叫堆疊),檢視整個程式的呼叫堆疊一般來說根據呼叫關係知道引起記憶體洩漏的原因。

注意除錯過程中根據執行庫指定監視name

在multi-threaded debug(/mtd)即靜態鏈結下name項輸入_crtbreakalloc;

在multi-threaded debug dll(/mdd)即動態鏈結下name項輸入_crtbreakalloc(msvcr90d根據具體的vs版本修改)。

參考:

利用CRT庫函式檢查記憶體洩漏

利用crt庫函式檢查記憶體洩漏 條件 1.在debug模式下。2.define crtdbg map alloc include stdlib.h include crtdbg.h crtdumpmemoryleaks 可以列印出目前為止沒有釋放的已申請記憶體。necessary define cr...

Visual Studio記憶體洩漏除錯

在可能洩漏的檔案頭部加入下面幾行 保證malloc和new的洩漏都可以檢測到 define crtdbg map alloc include ifdef debug 過載new運算子 define new new normal block,file line endif 然後在程式中加入下面 程式執...

Linux mtrace除錯記憶體洩漏

本文只介紹乙個實用的linux小命令 mtrace memory trace 它能夠用來協助定位記憶體洩露 linux下測試 4 trace.c include includeint main 編譯 gcc 4 trace.c o 4 trace g ddebug 因為我 中沒有debug巨集控制,...