1. 程式人生 > >堆破壞(Heap Corruption)和Gflags

堆破壞(Heap Corruption)和Gflags

什麼是Heap Corruption

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

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

fFrameSize=pSearch01To-fpBuffer;   //在某種情況下會出現fFrameSize = 0xFFFFFFFCmemcpy(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 pageFull模式的好處是“Sudden Death”,即在問題發生的點上立馬Access Violation,易於
    Debugging。壞處是大量消耗記憶體。
  1. Normal模式:在我們分配的每個記憶體塊前後加少量的填充欄位。Normal模式的好處是記憶體消耗較少。壞處是隻有在釋放記憶體時才會檢測出Heap CorruptionDebugging難度還是比較大。

PageHeap的使用方法

大家在WinDbg的安裝路徑下,可以看到gflags.exe這個工具,gflags集成了pageheap的功能。Gflags可以以GUI方式或Console方式執行,但是GUI方式只能啟用PageHeapFull模式,所以建議大家通過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

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

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