一次堆破壞的調試經歷

過程是這樣的,在vc debug的過程中,突然彈出了一個assert窗口:

 

Windows has triggered a breakpoint in cs.exe.

This may be due to a corruption of the heap, which indicates a bug in cs.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while cs.exe has focus.

 

查看output輸出:

Heap missing last entry in committed range near e664630

Windows has triggered a breakpoint in cs.exe.

 

This may be due to a corruption of the heap, which indicates a bug in cs.exe or any of the DLLs it has loaded.

 

不廢話,直接查看該內存是什麼:

0x0E664630  0e 00 0f 00 59 03 10 04 aa aa cd ab 00 10 72 85 38 00

看不出什麼,往上再看看:

0x0E66460C  07 e2 04 00 a8 01 66 0e 01 00 cd cd fd fd fd fd....

 

看來這就是塊堆內存,實在看不出什麼,決定暫時忽略. 過了幾天,該錯誤沒有再出現過.

 

但就在交付程序前一天測試中,又出現了這個錯誤.看來一顆定時炸彈是埋藏在了程序中.必須找出來,否則後果很嚴重.

 

首先要做的就是要重現這個問題,如果每次碰巧遇到這個問題的話,實在無從下手.從症狀來看,是個典型的Heap Corrupt.所以先使用工具:pageheap,以做到能夠百分百重現那個堆破壞.

 

page heap工具啓用的兩種方法:Full-page heap和Normal page heap

我先使用了Normal page heap 命令爲pageheap /enable xx.exe /normal

 

然後通過windbg設置符號表:x:/symbols_folder;srv*x:/symbols_folder*http://msdl.microsoft.com/download/symbols

 

開始各種調試,幾乎用遍了<<Windows高級調試>>這本書中指導的各種命令,(調試過程省略2000字)未果.幾乎崩潰時,突然看到書上的這麼一段話:

 

普通頁堆通過填充模式檢測堆塊破壞,需要再發生堆破壞之後再調用一次堆管理器.

完全頁堆除了特定的填充模式外,它還爲每個堆塊增加了防護頁,防護頁是一個頁不可訪問的內存,它被放置在堆塊的起始位置和結束位置上.防止堆塊上下溢出.

 

我靠,直接pageheap /enable xx.exe /full 設置完全頁堆模式.重新運行程序.

瞬間程序崩掉,這個激動呀.還是第一次看見程序崩掉那麼激動,查看崩潰的代碼:

原來是把一個類指針強轉爲另一個子類的指針,調用了子類的一個函數,但是該類不存在這個函數.同時這個子類函數裏面做了一次bool變量賦值,結果這個值就寫到了堆地址裏面去了.

 

總結

以後遇到類似問題,直接pageheap full 全開.

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