Share via


TechEd2008- .NET 應用程式除錯秘技系列(3) - Internet Explorer Crashed

在這個範例裏,會首度介紹WinDbg這個工具(之前有插播Kernel Debugging)。坦白說,在還沒有進微軟之前,我也不曉得有WinDbg這工具(謎之音:就算知道也不懂怎麼用啊~~),一切就在於國內關於這方面知識的介紹實在太少。我想也跟debugging本身並不是一門顯學也有關係。坊間的書大都教大家怎麼寫程式,但很少提到怎麼除錯。而實際上除錯也沒有想像中的簡單,除了對程式語言及邏輯的了解以外,還需要對系統的行為有所了解。

當然,除錯自己的程式總比除錯別人的程式來得容易(尤其是在有source code的狀況下)。反觀我們在幫客戶除錯時,大都沒有客戶的程式碼,這在難度上就更高了,甚至在某些狀況下,都要用合理的懷疑來判斷可能造成問題的原因。但也因此才能累積那麼多的經驗。

這個範例的專案可以在這裏下載。

這個問題是這樣的,使用IE去訪問一個簡單的ASP.NET 頁面,卻造成了IE Crash,而已幾乎每次都會發生。頁面與程式如下:

1) 頁面上只放了一個TreeView 控製項

019

2) 在Page_Load時讀取本機上的XML並將內容加到TreeView

020

3) 程式執行畫面如下:

021

4) 當點下連結後,IE 就Crash了(不見得點一次就會Crash,有時候要多點幾次)

022

當這樣的問題發生時,各位認為是ASP.NET網頁的問題還是IE的問題呢? 如果客戶跟你說,IE去瀏覽其他網頁都沒問題,而且用其他Browser訪問這個網頁也沒有問題,當下是不是也會覺得是產品的問題呢? 但不管是不是我們產品的問題,總是要解決嘛~ 既然這麼容易重現問題,我們可以用WinDbg來幫助我們做初步的分析。

但這時候問題又來了,到底我們要先看IIS的W3WP.exe還是IE的Iexplore.exe呢? 以經驗上來判斷,一個server side的網頁是不會造成用戶端的IE Crash的。因此我們將焦點放在IE, 看到底是什麼原因造成的IE 的Crash。

1) 首先我們再重新開啟IE並訪問有問題的網頁,然後開啟WinDbg並attach到Iexplore.exe這個處理序(Process)。

023 024

2) 當Windbg attach到IE時,一開始會先中斷下來(此時您無法操作IE),您必須輸入"g"這個指令(亦即go的意思),才能讓程式繼續執行。

026

3) 當指令列顯示如下時,就可以繼續操作IE

027

4) 這時候我們必須讓問題重現,當IE再次Crash時,WinDbg將會偵測到並中斷下來。此時我們輸入"k"這個指令,顯示目前執行緒的呼叫堆疊(Call Stacks)。

請注意紅色框起來的部份,在WinDbg中,除了方法的起始及返回的記憶體位址外,若有載入對應的symbol檔,就會顯示方法名稱以及參數等資訊。以下圖為例,在!左邊是模組名稱,右邊是方法名稱。因此Kernel32!HeapFree 表示程式在此處執行的是Kernel32.dll的HeapFree方法。

028

但HeapFree這個方法在作業系統已經好幾年了,是一個非常基本的方法,出問題的機率實在太低了。通常針對這樣的問題,我們會先看看是不是有其他非微軟的模組被載入並且正在執行,比較常見的有Flash Player啦或其他的Add-on,再不然就是廣告軟體、間碟軟體或病毒等。在這個例子中,我們看到呼叫HeapFree的是底下稱為Jccatch的QueryInterface的方法。但這並不是微軟的模組,因此若要檢視模組的詳細資訊,我們可以輸入"lmvm <Module Name>"此例為"lmvm jccatch",如下圖所示:

029

從上面的圖我們可以看到,這是一個Flashget的Add-on。有了這樣的訊息後,我們可以想想Flashget和IE的關聯性。FlashGet是很知名的下載軟體,他還會監視IE有沒有下載檔案的行為,進而取代IE進行下載的動作。由此我們可以測試看將IE裏與FlashGet相關的Add-on先暫時disable後,問題還會不會發生。

030

在Disable上圖所框選的3個Add-on後再進行測試,問題就不再發生了。

 

後記:其實這個範例還沒完全結束,原因是這個問題之所以會造成IE Crash,是由於Heap corruption所導致,因此不見得點一下TreeView上的Node都會造成IE Crash,有時要點好幾下,甚至點了不下50次問題都不會發生。但這個範例是很容易重現問題的。後續我們有機會再來介紹Gflag這個工具,針對Heap corruption的問題,使用Gflag可以加速問題重現。