VS檢測記憶體洩漏,定位洩漏程式碼位置方法
1、什麼是記憶體洩漏?
記憶體洩漏指的是在程式裡動態申請的記憶體在使用完後,沒有進行釋放,導致這部分記憶體沒有被系統回收,久而久之,可能導致程式記憶體不斷增大,系統記憶體不足……引發一系列災難性後果;(關於程式申請記憶體分配方式,詳見:記憶體分配方式)
2、零容忍
排除記憶體洩漏對於程式的穩健型特別重要,尤其是程式需要長時間、穩定地執行時。C++這類動態記憶體申請釋放都是由程式設計師控制的語言,稍不注意,很有可能就會有未釋放的記憶體。這類問題,雖然有的時候僅僅只是洩漏了幾個位元組,但是危害極大。因此,我們一般都是要做到:記憶體洩漏零容忍!!!
3、檢查、定位記憶體洩漏
檢查方法:
在main函式最後面一行,加上一句_CrtDumpMemoryLeaks()
Detected memory leaks!
Dumping objects ->
{453} normal block at 0x02432CA8, 868 bytes long.
Data: <404303374 > 34 30 34 33 30 33 33 37 34 00 00 00 00 00 00 00
{447} normal block at 0x024328B0, 868 bytes long.
Data: <404303374 > 34 30 34 33 30 33 33 37 34 00 00 00 00 00 00 00
{441} normal block at 0x024324B8, 868 bytes long.
Data: <404303374 > 34 30 34 33 30 33 33 37 34 00 00 00 00 00 00 00
{435} normal block at 0x024320C0, 868 bytes long.
Data: <404303374 > 34 30 34 33 30 33 33 37 34 00 00 00 00 00 00 00
{429} normal block at 0x02431CC8, 868 bytes long.
Data: <404303374 > 34 30 34 33 30 33 33 37 34 00 00 00 00 00 00 00
{212} normal block at 0x01E1BF30, 44 bytes long.
Data: <` > 60 B3 E1 01 CD CD CD CD CD CD CD CD CD CD CD CD
{204} normal block at 0x01E1B2C8, 24 bytes long.
Data: < > C8 B2 E1 01 C8 B2 E1 01 C8 B2 E1 01 CD CD CD CD
{138} normal block at 0x01E15680, 332 bytes long.
Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
{137} normal block at 0x01E15628, 24 bytes long.
Data: <(V (V (V > 28 56 E1 01 28 56 E1 01 28 56 E1 01 CD CD CD CD
Object dump complete.
程式“[4860] TradeServer.exe: 本機”已退出,返回值為 0 (0x0)。
取其中一條詳細說明:{453} normal block at 0x02432CA8, 868 bytes long.
被{}包圍的453就是我們需要的記憶體洩漏定位值,868 bytes long就是說這個地方有868位元記憶體沒有釋放。
接下來,定位程式碼位置:
在main函式第一行加上:_CrtSetBreakAlloc(453); 意思就是在申請453這塊記憶體的位置中斷。然後除錯程式,……程式中斷了。檢視呼叫堆疊
雙擊我們的程式碼呼叫的最後一個函式,這裡是CDbQuery::UpdateDatas(),就定位到了申請記憶體的程式碼:
好了,我們總算知道是哪裡出問題了,這塊記憶體沒有釋放啊。改程式碼,修復好這個。然後繼續…………,直到除錯輸出中沒有normal block ,程式沒有記憶體洩漏了。
記得加上標頭檔案:#include <crtdbg.h>
最後要注意一點的,並不是所有normal block一定就有記憶體洩漏,當你的程式中有全域性變數的時候,全域性變數的釋放示在main函式退出後,所以在main函式最後_CrtDumpMemoryLeaks()會認為全域性申請的記憶體沒有釋放,造成記憶體洩漏的假象。如何規避呢?我通常是把全域性變數宣告成指標在main函式中new 在main函式中delete,然後再呼叫_CrtDumpMemoryLeaks(),這樣就不會誤判了。