首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

生死疆界(上):從一段簡單代碼追溯 Debug 模式下的記憶體損壞報錯

     編輯:關於VC++

一切始於一段極簡單的代碼:

void main() {
    char *p = new char;
    cin >> p;
    cout << p[2];
    delete p;
}

輸入 abcd,螢幕正確輸出 c,但隨即彈出 Debug Error:DAMAGE: after Normal block(#64) at 0x003429f8。更詭異的是,若改為 cout << p; 且僅輸入單一字元 a,依然報錯。Release 模式卻一切正常,移除 delete p 錯誤也消失。問題核心在於 Debug 模式下的記憶體完整性檢查機制。

深入原始碼追蹤

在 delete p 設中斷點,按 F11 進入原始碼世界:

  1. DELOP.CPP:operator delete 僅呼叫 free(p)。
  2. DBGHEAP.C:Debug 堆積實作,最終在 _free_dbg 中遇到關鍵判斷:
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
    _RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%08X.\n", ...);

CheckBytes 負責驗證使用者資料區後方的 nNoMansLandSize(預設 4)個位元組是否全為 _bNoMansLandFill(0xFD)。若非,呼叫 _RPT3 產生錯誤報告。

CheckBytes 實作

static int __cdecl CheckBytes(unsigned char *pb, unsigned char bCheck, size_t nSize) {
    int bOkay = TRUE;
    while (nSize--) {
        if (*pb++ != bCheck) {
            _RPT3(_CRT_WARN, "memory check error at 0x%08X = 0x%02X, should be 0x%02X.\n", (BYTE*)(pb-1), *(pb-1), bCheck);
            bOkay = FALSE;
        }
    }
    return bOkay;
}

註釋說明:Purpose: verify byte range set to proper value。至此,原始碼追蹤到頭,仍未揭示哨兵何時、如何被植入。下一步必須直接監視記憶體,觀察 new char 執行前後的變化,才能揭開真相。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved