使用 CrtSetDbgFlag檢測記憶體洩露

2021-07-12 05:26:06 字數 3448 閱讀 2967

一、介紹:

動態分配、**記憶體是c/c++程式語言乙個最強的特點,但是中國哲學家孫(sun tzu,我不知道是誰?那位知道?)指出,最強的同時也是最弱的。這句話對c/c++應用來說非常正確,在記憶體處理出錯的地方通常就是bugs產生的地方。乙個最敏感和難檢測的bug就是記憶體洩漏-沒有把前邊分配的記憶體成功釋放,乙個小的記憶體洩漏可能不需要太注意,但是程式洩漏大塊記憶體,或者漸增式的洩漏記憶體可能引起的現象是:先是效能低下,再就是引起複雜的記憶體耗盡錯誤。最壞的是,乙個記憶體洩漏程式可能用完了如此多的記憶體以至於引起其他的程式出錯,留給使用者的是不能知道錯誤到底來自**。另外,乙個看上去無害的記憶體洩漏可能是另乙個問題的先兆。幸運的是vc++debuger和crt庫提供了一組有效的檢測和定位記憶體洩漏的工具。本文描述如何使用這些工具有效和系統的排除記憶體洩漏。

_crtdumpmemoryleaks()就是檢測從程式開始到執行該函式程序的堆使用情況,通過使用_crtdumpmemoryleaks()我們可以進行簡單的記憶體洩露檢測。

啟用記憶體洩露檢測:

檢測記憶體洩漏的主要工具是偵錯程式和 c 執行時庫 (crt) 除錯堆函式。若要啟用除錯堆函式,請在程式中包括以下語句:

#define _crtdbg_map_alloc  

#include

#include

注意:

#include必須按照以上所示順序。如果更改了順序,所使用的函式可能無法使用。
通過包括crtdbg.h,將 malloc 和 free 函式對映到其「debug」版本 _malloc_dbg 和 _free_dbg,這些函式將跟蹤記憶體分配和釋放。此對映只在除錯版本(在其中定義了_debug)中發生。發布版本使用普通的malloc 和 free 函式。

注意:在編譯時要把工程屬性中的「**生成」中的「執行時庫」改為:「多執行緒除錯(/mtd)」,否則編譯報以下錯:

1>正在鏈結...

1>link : 沒有找到 c:\users\chenyj\desktop\test\debug\test.exe 或上乙個增量鏈結沒有生成它;正在執行完全鏈結

1>main.obj : error lnk2019: 無法解析的外部符號 "void * __cdecl operator new(unsigned int,int,char const *,int)" (??2@yapaxihpbdh@z),該符號在函式 "void * __cdecl operator new(unsigned int)" (??2@yapaxi@z) 中被引用

1>main.obj : error lnk2019: 無法解析的外部符號 __crtdumpmemoryleaks,該符號在函式 _main 中被引用

1>main.obj : error lnk2019: 無法解析的外部符號 "void * __cdecl operator new(unsigned int,int,char const *,int)" (??_u@yapaxihpbdh@z),該符號在函式 _main 中被引用

#define語句將 crt 堆函式的基版本對映到對應的「debug」版本。並非絕對需要該語句,但如果沒有該語句,記憶體洩漏轉儲包含的有用資訊將較少。
在新增了上面所示語句之後,可以通過在程式中包括以下語句來轉儲記憶體洩漏資訊:

_crtdumpmemoryleaks()

使用示範:

#define _crtdbg_map_alloc  

#include

#include

#define new new(_client_block, __file__, __line__)

int main()

這個示範程式與前面講的多了乙個巨集定義:

#define new

new( _client_block, __file__, __line__)

程式除錯後在「輸出」視窗輸出如下:

detected memory leaks!  

dumping objects ->

.\main.cpp(15) : client block at 0x005f0f90, subtype 0, 40 bytes long.

data: < > cd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cd

object dump complete.

「輸出」很明顯的告訴了你在test.cpp檔案的第57行分配了乙個40位元組的記憶體而沒有釋放。在「輸出」視窗中選擇包含檔名和行號的行,然後按 f4 鍵即可進入到原始檔中分配記憶體的行。

現在我們再來看看如果不加之前那個new的巨集定義會出現怎麼樣的結果。

程式除錯後在「輸出」視窗輸出如下:

detected memory leaks!

dumping objects ->

normal block at 0x00392bb0, 40 bytes long.

data: <> cd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cdobject dump complete.

與之前的對比,這次的輸出並沒有告訴我們這個記憶體洩露具體是在哪個位置引起的。另外如果沒定義

#define_crtdbg_map_alloc
也會引起同樣的結果。

二、

//on_ff 為true 列印記憶體洩漏, 為false則不列印  

void detect_memory_leaks( bool on_off )

_crtsetdbgflag( flags );

}

這個函式在主程式的入口處呼叫,在程式正常退出時會列印出記憶體洩漏

測試程式

int _tmain(int argc, _tchar* argv)  

控制台列印資訊:

detected memory leaks!

dumping objects ->

normal block at 0x0039bc90, 20 bytes long.

data: < > cd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cdcd

cdobject dump complete.

請按任意鍵繼續. . .

測試環境:win32 xp vc2008

使用GraphEdit使用

1 註冊元件。其實乙個filter就是乙個com元件,所以使用之前需要註冊,可以有兩種方法對元件進行註冊。1.直接使用命令。命令列下輸入 regsvr32 hqtlystd.ax 編譯之後你會在工程目錄下的debug中找到hqtlystd.ax,這個就是要用的filter 即可註冊成功。2.vc6....

MySQL使用學習使用 mysql學習使用

1 mysql學習 1 安裝 ubuntu下直接安裝 apt get install mysql server 2 檢查伺服器是否啟動 sudo netstat tap grep mysql,如果啟動成功,出現以下資訊 tcp00localhost.localdomain mysql listen ...

學習使用CSDN markdown使用

建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 你好!這是你第一次使用markdown編輯器所展示的歡迎頁。如果你想學習如何使用markdown編輯器,可以仔細閱讀這篇文章,了解一下mar...