使用gflags來檢測heap問題

2021-06-28 05:23:24 字數 3496 閱讀 3530

gflags是windows debug tools 工具包下的乙個工具,在windows 2000的resource kit中也可以找得到。用來設定一些除錯屬性,總體上分為3個級別system,kernel和image file。我們設定好path環境變數,將其指向debug tools工具的目錄下。

gflags

- 老牌的pageheap配置工具,有命令列和gui兩種操作方式,功能比較全,包含在windbg偵錯程式安裝包內。同樣在windows 2000 professional sp2 以上可用。

一些使用gflags命令列的例子:

配置正常頁堆:

"c:\program files\debugging tools for windows (x86)\gflags.exe" /p /enable qq.exe

配置完全頁堆:

"c:\program files\debugging tools for windows (x86)\gflags.exe" /p /enable qq.exe /full

列出當前啟動了頁堆的程序列表:

"c:\program files\debugging tools for windows (x86)\gflags.exe" /p

取消頁堆設定:

"c:\program files\debugging tools for windows (x86)\gflags.exe" /p /disable qq.exe

一些特殊選項解釋:

/unaligned

這個選項只能用於完全頁堆。當我們從普通堆管理器分配一塊記憶體時,記憶體總是8位元組對齊的,頁堆預設情況下也會使用這個對齊規則,但是這會導致分配的記憶體塊的結尾不能跟頁邊界精確對齊,可能存在0-7個位元組的間隙,顯然,對位於間隙範圍內的訪問是不會被立即發現。更準確的說,讀操作將永遠不能被發現,寫操作則要等到記憶體塊釋放時校驗間隙空間內的填充資訊時才發現。/unaligned用於修正這個缺陷,它指定頁堆管理器不必遵守8位元組對齊規則,保證記憶體塊尾部精確對齊頁邊界。

需要注意的是,一些程式啟用這個選項可能出現異常,例如ie和qq就不支援。

/backwards

這個選項只能用於完全頁堆。這個選項使得分配的記憶體塊頭部與頁邊界對齊(而不是尾部與邊界對齊),通過這個選項來檢查頭部的訪問越界。

/debug

指定一啟動程序即attach到偵錯程式,對於那些不能自動生成dump的程式,是比較有用的選項。

完全頁堆:

當分配一塊記憶體時,通過調整記憶體塊的分配位置,使其結尾恰好與系統分頁邊界對齊,然後在邊界處再多分配乙個不可訪問的頁作為保護區域。這樣,一旦出現記憶體讀/寫越界時,程序就會crash,從而幫助及時檢查記憶體越界。

因為每次分配的記憶體都要以這種形式布局,尤其對於小片的記憶體分配,即使分配乙個位元組,也要分配乙個記憶體頁,和乙個保留的虛擬記憶體頁(注意在目前的實現中,這個用作邊界保護區域的頁從來不會被提交)。這就需要大量的記憶體,到底乙個程序需要多少記憶體,很難估算,因此在使用page heap前,至少保證你的機器至少設定了1g虛擬記憶體以上。

正常頁堆

正常頁堆原理與crt除錯記憶體分配函式類似,通過分配少量的填充資訊,在釋放記憶體塊時檢查填充區域。來檢測記憶體是否被損壞,此方法的優點是極大的減少了記憶體耗用量。缺點是只能在釋放塊時檢測,不太好跟蹤出錯的**位置。

頁堆能處理的錯誤型別:

錯誤型別正常頁堆整頁堆

堆控制代碼無效 

立即發現 

立即發現 

堆記憶體塊指標無效 

立即發現 

立即發現 

多執行緒訪問堆不同步 

立即發現 

立即發現 

假設重新分配返回相同位址(realloc) 

90% 記憶體釋放後發現 

90% 立即發現 

記憶體塊重複釋放 

90% 立即發現 

90% 立即發現 

訪問已釋放的記憶體塊 

90% 在實際釋放後發現 

90% 立即發現 

訪問塊結尾之後的內容 

在釋放後發現 

立即發現 

訪問塊開始之前的內容 

在釋放後發現 

立即發現 

以下是舉例:

前期工作: 將gflags(預設安裝在c:\program files\debugging tools for windows (x86))加入到path

案例1:

int _tmain(int argc, _tchar* argv)

程式本身是有問題的。陣列已經越界,但是debug模式下並不報錯,release模式下也很大可能是不crash的。

在命令提示符下執行:

>gflags /p /enable test.exe /full

在release模式執行test.exe。exception將直接定位到 p[8] = 10; 這一行

案例2:

int _tmain(int argc, _tchar* argv)

以上**和案例1僅有一點不同,就是陣列大小。但是如果執行

gflags /p /enable test.exe /full

在release模式下並不會出現exception並定位到 p[9] = 10;

原因是沒有設定/unaligned引數,具體看說明。案例2中,陣列有9位元組大小,按記憶體8位元組對齊的說法,這塊記憶體應該是

16位元組,後面還有7位元組的空間,所以 p[9] = 10; 並不會產生exception。設定 /unaligned 引數,禁止8位元組對齊,就

可以跟蹤到 p[9] = 10; 這個exception

>gflags /p /enable test.exe /full /unaligned

案例3:

class a

};int _tmain(int argc, _tchar* argv)

在debug模式下可能產生exception:

heap:   free   heap   block   ******xx modified   at   ******xx  after   it   was   freed

在release模式下執行並不報錯,但是程式本身是有問題的,delete this; 之後,又給成員變數 a=10;

這顯然是不對的。

>gflags /p /enable test.exe /full

此時在debug下執行程式,會產生exception,並定位到   a = 10;

原 使用Gflags來檢測heap問題

gflags是windows debug tools 工具包下的乙個工具,在windows 2000的resource kit中也可以找得到。用來設定一些除錯屬性,總體上分為3個級別system,kernel和image file。我們設定好path環境變數,將其指向debug tools工具的目錄...

gflags 工具使用小記

windows下,除錯mysql乙個記憶體被破壞的bug,構造最小重現用例,執行,出現問題,用偵錯程式檢視,檢視 不得其解.於是使用gflags工具 非google的那個開源的處理命令列引數的庫 用法可參考 1 官方文件 2 部落格 如以上資料所述,執行 1 命令列執行 gflags p enabl...

gFlags 使用指南

最近看到的乙個示例 中有使用gflags,就去簡單查了一下資料學習一下。github 官方使用文件 gflags簡明教程 gflags使用文件 gflags是google開源的一套命令列引數處理的開源庫,包括c 的版本和python 版本。和 getopt 之類的庫不同,flag的定義可以散布在各個...