挑戰:32 位虛擬位址空間壓力與 64 位移植雙維護
現有工具 (Purify、Insure++) 專注已配置區塊,但虛擬記憶體壓力來自已提交位址空間。洩漏、碎片、區塊內浪費、延遲重分配皆導致不必要的虛擬記憶體提交。本地代碼無 GC 壓縮堆能力,區塊位置不確定,必須主動追蹤堆範圍與區塊存取模式。
核心機制:自定義配置器 + 條件編譯偵錯版
封裝 malloc/free/realloc,追蹤每個區塊與堆範圍,僅在偵錯版啟用,釋出版零開銷。
資料結構
- 區塊追蹤表:基址、大小、
accessed 標記 (上次提交後是否被存取)。
- 堆範圍追蹤表:基址、大小 (對應
HeapWalk 或系統調用獲取)。
配置流程 (演算法 1)
- 新區塊加入追蹤表,標記
accessed=false。
- 若觸發虛擬記憶體提交 (系統調用判斷):
- 屬現有堆範圍 → 擴展該範圍上限。
- 新堆範圍 → 建立新追蹤項。
釋放流程 (演算法 2)
- 若區塊未在追蹤表 → 忽略。
- 檢查區塊所在虛擬記憶體是否已解除提交 (嘗試讀取捕捉存取違例,或
IsBadReadPointer)。
- 若範圍變更:呼叫
HeapWalk 更新鄰近剩餘提交範圍;若無剩餘則刪除堆範圍項。
- 區塊未被存取過即釋放 → 報導潛在浪費。
重配置流程
先按釋放邏輯移除舊區塊,再按配置邏輯加入新區塊 (位址可能變動)。若位址不變且增長,檢查堆擴展。
存取標記與清理時機
- 若所有堆存取經由存取函式 (get/set),在其中設定
accessed=true。
- 每次虛擬記憶體提交時,重置所有區塊
accessed=false。
- 釋放未被存取區塊 → 先釋放區塊 → 縮減虛擬記憶體覆蓋範圍。
- 定期掃描:經多輪仍未存取且獨佔提交範圍 → 釋放並重新定位 (類似手動 GC)。
多堆支援與效能優化
- 每個堆 (HeapCreate、多 CRT 實例) 維護獨立追蹤表,查找更快、銷毀堆時一併清理。
- 追蹤表查找用二分搜尋、跳表或雜湊加速。
- 偵錯版速度下降可接受,換取虛擬記憶體優化的巨大回報。
專業工具輔助
Purify/Insure++ 等可追蹤區塊、堆範圍、虛擬記憶體雜湊值,提供更可靠運行時錯誤偵測,但核心邏輯同本文策略。