1. 程式人生 > >VS檢測記憶體洩漏,定位洩漏程式碼位置方法

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(),這樣就不會誤判了。