1. 程式人生 > >記憶體洩露檢測方法

記憶體洩露檢測方法

轉自:https://blog.csdn.net/whatday/article/details/50427101

方法一、

1、標頭檔案:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
 注意 
#include 語句必須採用上文所示順序。如果更改了順序,所使用的函式可能無法正確工作。 

2、在添加了上面所示語句之後,可以通過在程式中包括以下語句來轉儲記憶體洩漏資訊:
_CrtDumpMemoryLeaks();//在最後一個語句新增

或通過下面方法新增。
_CrtSetDbgFlag
如果程式總是在同一位置退出,呼叫 _CrtDumpMemoryLeaks 將非常容易。如果程式從多個位置退出,則

無需在每個可能退出的位置放置對 _CrtDumpMemoryLeaks 的呼叫,而可以在程式開始處包含以下呼叫:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

方法二、通過記憶體狀態比較
 1、功能:可以檢測某段程式碼間的記憶體洩露.
    描述: 若要確定程式碼中某一部分是否發生了記憶體洩漏,可以在該部分之前和之後對記憶體狀態拍快照

,然後使用 _CrtMemDifference 比較這兩個狀態:

_CrtMemState s1, s2, s3;  
  
    _CrtMemCheckpoint(&s1);  
    // memory allocations take place here  
    _CrtMemCheckpoint(&s2);  
  
    if (_CrtMemDifference(&s3, &s1, &s2))  
    {  
        //列印記憶體洩露  
        _CrtMemDumpStatistics(&s3);  
    }  
    else  
    {  
        //無洩露  
    }  

方法三、

有些記憶體洩露是不會dump出來詳細資訊的,只會給出記憶體塊號,這種情況一下一般可以用一下方法調試出來。

  這兩天調一個程式,發現每次退出都有記憶體洩漏,在此總結一個除錯記憶體洩漏的好方法。

    對於比較明顯的記憶體洩漏,vc2008是比較容易定位的,在Debug模式F5執行,退出時會列出引起記憶體洩漏的問題程式碼所在檔案及行號;但如果是比較隱蔽的記憶體洩漏,Output輸出視窗只會輸出部分資訊,形式如下:

    Detected memory leaks!
    Dumping objects ->
    {858} normal block at 0x003ED290, 12 bytes long.
    Data: < \H         > A0 5C 48 00 00 00 00 00 00 00 00 00
    Object dump complete.

    我們來看一下輸出資訊的格式。

    {xxx} — 表示程式執行後第xxx次記憶體分配發生了洩漏,即記憶體分配編號;

    xxx block — 表示記憶體塊型別,包括三種:普通(normal)、客戶端(client)和執行時(CRT);

    at 0xFFFFFFFF — 表示發生洩漏的記憶體地址,用十六進位制表示;

    xx bytes long — 表示發生洩漏的記憶體大小;

    Data:xxx — 表示記憶體資料資訊,一般輸出前16位元組的內容。

    記憶體洩漏的地址、大小和資料資訊很難對我們的定位起到有效地幫助,但是如果我們能夠讓程式停在分配有洩漏的記憶體的地方,然後根據呼叫堆疊(Call Stack)裡的資訊,就可以很方便的定位是哪個語句出現問題。幸運的是,VC的C執行庫(C run-time library)為我們提供了一個這樣的函式:CrtSetBreakAlloc,宣告如下: 

long _CrtSetBreakAlloc( long lBreakAlloc );

    其中引數lBreakAlloc即為記憶體分配號(花括號中的數字)。我們只要在程式初始化函式中新增語句:_CrtSetBreakAlloc(858)就可以使程式在Debug F5執行時自動斷點到我們想要的位置。

    使用這個函式進行記憶體洩漏定位有個條件,即發生記憶體洩漏的分配號是固定的,每次啟動程式不會隨機變化。

    但是如果我們的程式比較大,記憶體洩漏也不止一個,用上面的方法除錯可能會很麻煩,需要經常更新程式碼並重新編譯程式。使用下面的方法更方便

    首先確定自己的程式使用的是哪個C執行庫,方法是程式Propertise -> C/C++ -> Code Generation -> Runtime Library選項,若為Multi-threaded Debug(/MTd),則為靜態連結,若為Multi-threaded Debug DLL(/MDd),則為動態連結。

    然後按F11啟動程式,程式會停在入口點。此時調出Watch視窗,

    靜態連結 在name項中輸入_crtBreakAlloc,在value項中輸入你要定位的記憶體分配編號;

    動態連結 在name項中輸入{,,msvcr90d.dll}_crtBreakAlloc,在value項中輸入記憶體分配號。注意msvcr90d.dll是vc2008環境使用的執行庫dll,若你用的是其他版本vc,請換成對應版本的dll。

    現在按F5執行,程式就會自動定位到你要除錯的記憶體分配語句,這時候看call stack的資訊會很有幫助。

    這個辦法使用起來非常靈活,只要你確定記憶體分配號是不變的,就可以方便地為程式設定斷點了,省去了更新程式碼和編譯的麻煩。這個方法幾乎是當前進行記憶體洩漏除錯的最有效方法,如果你發現記憶體洩漏的分配號是變化的,可以想辦法去掉一些沒有問題的記憶體申請(多半是介面和多執行緒涉及到的申請),儘量使有問題的分配固定,就可以用這個方法排錯了。