記憶體管理和偵錯堆積
這個主題適用於:
版本 |
Visual Basic |
C# |
F# |
C++ |
Web Developer |
---|---|---|---|---|---|
Express |
僅適用原生 |
||||
Pro、Premium 和 Ultimate |
僅適用原生 |
開發人員最常面臨的兩種難解決的問題是,覆寫配置緩衝區的結尾和記憶體遺漏 (無法在不再需要時釋放配置)。 偵錯堆積提供的強大工具,可以解決這類的記憶體配置問題。
堆積函式的偵錯版本
堆積函式的偵錯版本是呼叫發行版本裡使用之函式的標準或基底版本。 當您要求記憶體區塊時,偵錯堆積管理員會從基底堆積配置比要求稍微大一點的記憶體區塊,並且傳回此區塊部分的指標。 例如,假設您的應用程式包含呼叫:malloc( 10 )。 在發行組建裡,malloc 會呼叫要求 10 位元組的基底堆積配置常式。 然而在偵錯組建裡,malloc 會呼叫 _malloc_dbg,它會呼叫要求 10 位元組加上大約 36 位元組的額外記憶體配置的基底堆積配置常式。 偵錯堆積裡所有產生的記憶體區塊會在單向連結串列 (Single-Linked List) 中完成連接 (依配置時間排列順序)。
偵錯堆積常式配置的額外記憶體是用於簿記資訊,這些資訊可能為將偵錯記憶體區塊連結在一起的指標,和用來捕捉配置區域覆寫的資料每端的小型緩衝區。
目前,用於儲存偵錯堆積的簿記資訊的區塊標頭結構會根據 DBGINT.H 標頭檔來宣告:
typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
struct _CrtMemBlockHeader *pBlockHeaderPrev;
char *szFileName; // File name
int nLine; // Line number
size_t nDataSize; // Size of user block
int nBlockUse; // Type of block
long lRequest; // Allocation number
// Buffer just before (lower than) the user's memory:
unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;
/* In an actual memory block in the debug heap,
* this structure is followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
目前在區塊使用者資料區的每一端的 NoMansLand 緩衝區大小是 4 位元組,而且會填入偵錯堆積常式所使用的已知位元組值,以確認沒有覆寫使用者記憶體區塊的限制。 偵錯堆積也會以一個已知值來填寫新的記憶體區塊。 如果您打算像以下的說明所述,維持堆積連結串列中的釋放區塊,這些釋放區塊也會填入一個已知值。 目前,使用的實際位元組值如下:
NoMansLand (0xFD)
在應用程式使用記憶體的每端的 "NoMansLand" 緩衝區目前是填入 0xFD。釋放區塊 (0xDD)
當 _CRTDBG_DELAY_FREE_MEM_DF 旗標設定時,偵錯堆積中的連結串列保持未使用的釋放區塊目前是填入 0xDD。新物件 (0xCD)
新物件在配置時會填入 0xCD。