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

生死疆界(下):深入剖析 new 與 delete 之間的記憶體檢測機制

     編輯:關於VC++

承接上一篇,我們在 delete p; 前設下中斷點,啟動偵錯並輸入 abcd,觀察記憶體位址 0x00342c40 的內容。字串 abcd 後緊跟著 0x00 結束符,一切看似正常。但錯誤依然發生,甚至改用 delete[] p 也無濟於事。問題的關鍵不在 delete 當下,而在更早的 new char 執行後,記憶體已被佈下「天羅地網」。

記憶體邊界哨兵:0xFD

重新啟動程式,從一開始就監視記憶體:

// new char 執行前
00342C40  EE FE EE FE EE FE EE  (未初始化堆積填充模式)
// new char 執行後
00342C40  CD FD FD FD FD F0 AD  (CD = 用戶資料區, FD FD FD FD = 4 個哨兵位元組)
00342C47  BA 0D F0 AD BA 0D F0

輸入 ab 後:

00342C40  61 62 00 FD FD F0 AD  (ab\0 覆蓋了第一個 FD)

偵錯執行期(Debug CRT)在使用者分配區後方放置 nNoMansLandSize = 4 個 _bNoMansLandFill = 0xFD 作為邊界哨兵。CheckBytes 函數會在 delete 時檢查這四個位元組是否全為 0xFD;若被覆寫(如 cin 寫入的 \0),即判定為緩衝區溢位,觸發 _RPT3 報錯 DAMAGE: after Normal block。

為何輸入單一字元也會出錯?

char *p = new char; 僅分配 1 位元組使用者空間,緊接著 4 個 0xFD。cin >> p 讀入 a 後會自動附加 \0,佔用 2 位元組,導致第一個哨兵 0xFD 被覆寫為 0x00,delete 時檢測失敗。若改為 new char[2],使用者空間變 2 位元組,ab\0 剛好填滿,哨兵倖存,程式不再報錯。

結論

四個 0xFD 就是堆積記憶體的「生死疆界」。Debug 版 CRT 透過在分配區尾部植入已知模式,並在釋放時驗證,以此偵測緩衝區溢位。Release 版移除此機制,因此不會報錯,但隱患依然存在。正確做法是:配合 new[] 使用 delete[],並確保寫入資料不超出分配大小。

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