天天看點

堆破壞(Heap Corruption)和Gflags什麼是Heap CorruptionHeap Corruption的危害PageHeap檢測Heap Corruption的原理PageHeap的使用方法其他相關工具寫程式過程中預防Heap Corruption

什麼是Heap Corruption

 堆破壞是記憶體破壞的一種,簡單來說就是由于程式的錯誤導緻堆記憶體被意外改寫,典型的情況包括:

  1. 申請了N個Bytes的記憶體,卻試圖寫入> N個Bytes的内容;
  2. 向已經釋放的記憶體位置寫入内容;

fFrameSize = pSearch01To - fpBuffer;    // 在某種情況下會出現fFrameSize = 0xFFFFFFFC

memcpy(fTo, fpBuffer, fFrameSize);      // 這裡memcpy會發生什麼?

Heap Corruption的危害

把不屬于自己的記憶體塊的内容改寫掉,危害是很顯然的。更要命的是,Heap Corruption的問題往往很難排查,因為:

  1. 每次運作表現出來的現象可能不一樣;
  2. Debug版和Release版表現可能不一樣;
  3. 問題暴露的地方和問題引入的地方可能相差很遠,兩者邏輯上沒有必然聯系;

PageHeap檢測Heap Corruption的原理

PageHeap工具可以在運作時檢測Heap Corruption,其基本原理是在我們配置設定的記憶體塊前後加上一些額外資訊,這些額外資訊用以檢測是否出現越界寫的情況。PageHeap分為Full模式和Normal模式:

  1. Full模式:在我們配置設定的每個記憶體塊尾上加一頁non-accessible page。Full模式的好處是“Sudden Death”,即在問題發生的點上立馬Access Violation,易于Debugging。壞處是大量消耗記憶體。
  1. Normal模式:在我們配置設定的每個記憶體塊前後加少量的填充字段。Normal模式的好處是記憶體消耗較少。壞處是隻有在釋放記憶體時才會檢測出Heap Corruption,Debugging難度還是比較大。

PageHeap的使用方法

大家在WinDbg的安裝路徑下,可以看到gflags.exe這個工具,gflags內建了pageheap的功能。Gflags可以以GUI方式或Console方式運作,但是GUI方式隻能啟用PageHeap的Full模式,是以建議大家通過Console方式來使用gflags(以Run As Administrator方式打開Cmd視窗運作gflags)。

幾條基本指令如下:

Gflags.exe /p /enable dest.exe

Gflags.exe /p /disable dest.exe

Gflags.exe /p

具體使用方法可以在WinDbg的幫助文檔中搜尋PageHeap,或在指令行模式下gflags /p /?

其他相關工具

除了gflags\pageheap之外,Application Verifier也可以用來檢測Heap Corruption問題。Application Verifier也包含了其他很多運作時檢查項,大家可以在工作中按需使用。Application Verifier的問題是它不支援托管代碼。

寫程式過程中預防Heap Corruption

PageHeap、Application Verifier或其他的運作時檢查工具其實都是事後諸葛亮;對我們來說更重要的是在每天寫程式的過程中就控制住,不給Heap Corruption機會。控制方法不止一種,就我們目前的情況來說,有兩點是可以立即做的:

  1. Klocwork靜态代碼檢查:Klocwork不能幫我們查出所有的Heap Corruption,但實踐證明還是能查出一部分的;
  2. 使用安全的函數:就是xxx_s,如memcpy_s等;對于我們自己寫的涉及記憶體操作的函數,也應設計成安全的。

繼續閱讀