使用Windbg在XP下Heap追蹤失敗的原因

1、故事背景
     最近同事的代碼中碰到一個bug會導致奔潰的bug,從dump上看是由於某個對象的堆內存指針被釋放了,但代碼仍調用了該對象指針的虛函數,從而引起內存訪問違法崩潰,由於該類被大量使用,無法直接定位到具體哪個類被提前釋放了,從而打算開啓堆頁檢查,跟蹤該對象堆內存指針被釋放的代碼位置,從而揪出元兇。
     由於此bug在win7的機器上不易重現,在xp sp3的機器上較容易重現,故準備在xp sp3的機器上開啓堆頁檢查(DHP),跟蹤該對象指針被釋放的代碼位置和時機,由於未從用過gflag進行堆頁檢查和調試,故先寫了段小代碼練練手:


用gflag開啓堆頁檢查:

    設好符號文件後祭出 Windbg 走起,崩潰觸發後斷下,輸入 !heap -p -a ecx 指令一舉揪出元兇,但現實卻是如此的骨感:
004010d9 8b11            mov     edx,dword ptr [ecx]  ds:0023:0161cff0=????????

0:000> !heap -p -a ecx

ReadMemory error for address eeddccee

Use `!address eeddccee' to check validity of the address.
注:此處 ecx = pCTest

"mov     edx,dword ptr [ecx]"表示取虛表指針 

Windbg提示的讀取內存錯誤,且改地址的內容無法顯示,查看下該內存地址屬性:

0:000> !address ecx

    015d0000 : 0161b000 - 000b5000

                    Type     00020000 MEM_PRIVATE

                    Protect  00000001 PAGE_NOACCESS

                    State    00001000 MEM_COMMIT

                    Usage    RegionUsagePageHeap

                    Handle   015d1000
address命令正確的指示了該地址爲私有堆內存,但該內存頁不可訪問。
     難道是堆頁開啓不正確?檢查註冊表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options,確定已經正確的設置了,嘗試其他多種設置,甚至換工具進行設置,但結依然如此。難道是機器問題?於是在win7 32位機器上重複上述過程,發現是可以正確的打印出堆內存指針被釋放的棧回溯的:

     但更換其他xp機器依然不能正確顯示。百度搜索無果,仔細看glfag使用說明和各項設置文檔也無果,最後去翻了翻 Windows 調試的權威書《軟件調試》關於頁堆的章節,並按照該書666頁查找棧回溯數據庫的方法查了下所有UST數據庫的回溯記錄,找到了"CTEST* pCTest = new CTEST(); "的棧回溯機率,即申請堆內存的記錄,但始終未找到釋放堆內存的記錄。於是再次懷疑xp下的頁堆並沒有真正啓動或啓動是有問題的,於是檢查下頁堆啓動情況:

    驚現“ReadMemory error for address eeddccee”,且只展示一個Page Heap句柄了,剩下的未展示完全,但頁堆明明白白的現實已經開啓,也有了準頁堆,但數據卻顯示不出來,說明數據可能被破壞,但測試代碼如此簡單,而且也被windbg第一時間斷下,不可能去破壞數據,難道是Windbg讀取有問題?於是再次對此疑問進行google,果然有個外國朋友也碰到了類似的問題,其在帖子中提出換成6.6.0007.5版即可解決,試了下果然在xp下順利輸出了用戶態棧回溯。那麼爲什麼高版本的Windbg會出現此問題呢?
     我想起在查找UST數據結構的時候,發現和《軟件調試》上寫的不一致,當時疑惑了下沒有在意,再次翻出來對比發現:

            Win7下StackTraceDataBase結構


                                                                   XP下StackTraceDataBase結構

Win7下的 _STACK_TRACE_DATABASE 結構和xp下並不完全相同,關鍵的 Buckets(棧回溯記錄)的結構偏移改了,而且原xp下是個數組,但win7下卻變成了鏈表,故猜測高版本的Windbg在xp下依然使用了win7下的某些數據結構,從而導致Windbg解析出了問題,不知道算不算微軟的bug。

由於低版本的Windbg已經很難找到了,故這裏也放出我找到的6.6.0007.5版:
Widnbg6.6.0007.5.exe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章