Windows Phone App的dump檔案執行個體分析-Stack Overflow

來源:互聯網
上載者:User

標籤:

前言

這篇文章我們一起來分析一個從Windows Phone Dev Center上下載下來的dump file。首先按照我上一篇的步驟設定好我們的Windbg,並按住Ctrl +D開啟dumpfile。可以看到下面的介面:

分析一個dump file可以分解為4個步驟,第一步是資訊收集,第二步是定位異常上下文,第三步分析和推理出現問題的原因,第四步分析和定位我們的原始碼並進行修複和驗證。 資訊收集

我們可以使用一些命令瀏覽一下這個dump file對應的系統版本和一些模組的資訊輔助我們後面的分析。

1. version命令,查看系統版本號碼

2. lm命令,顯示當前載入的模組。

可以使用lmv命令查看所有模組的詳細資料,如果想看某一模組的詳細資料,需要使用參數m,比如查看System_Data_Linq_ni.dll的詳細資料,”lmv mSystem_Data_Linq_ni”

定位異常上下文

當異常發生的時候,寄存器的上下文會被異常分發器儲存在棧上。我們可以通過一些方法找到並恢複發生異常時候的上下文,從上下文中找到我們需要的資訊,這裡使用”!analyze -v”命令。

1. 首先確認發生異常的線程。有時候發生異常的線程不止一個,我們在使用 “!analyze –v”之前需要確認發生異常的線程。使用”~* kvb”命令來查看所有線程的呼叫堆疊。”~*“ 命令是枚舉所有的線程,”kvb“命令是列出線程的呼叫堆疊。

可以發現所有的線程都是等待狀態,只有線程0不是,從線程0的callstack可以看出來線程0就是我們要找的發生異常的那個線程,。

2. 切換到發生異常的線程,”~0 s”

3. 使用“!analyze –v”,這個擴充命令來協助我們找到發生異常時候的上下文,並顯示當時的呼叫堆疊,有些情況下給出的呼叫堆疊並不是發生異常的第一現場,遇到這種情況我們需要進一步分析。

分析和推測

在上面的顯示中,我們發現一個很有意思的託管呼叫堆疊,裡面反覆出現了”System.Diagnostics.StackTrace..ctor()+0x12”。看起來StackTrack這個類型的對象在構造的時候調用了自己的成員函數GetStackFramesInternal,而這個函數又去構造了新的StackTrack的對象,如此反覆以至於發生了迴圈調用而導致棧被耗盡,這裡並沒有給出與我們的代碼相關的調用,看起來很像一個.net framework的bug。那麼為什麼會發生這樣的調用呢?讓我們繼續進行分析,看看是哪裡引發了這個調用。

為了找到更多的線索,我們可以進一步查看發生異常的線程棧裡都保留了什麼,我們可以通過”!teb”命令來查看當前線程的屬性,並找到棧的基址和大小,有了棧的基址和大小,我們就可以查看裡面的內容了。

1. 查看當前線程的屬性,”!teb”命令

2. ”dps + 位址範圍”命令可以讓我們查看棧裡面保留的資訊。

跳過這些無效的內容,我們繼續往後查看。

紅線的模組和函數正是我們App中的代碼,我們可以做一個大膽的推理在這裡。我們的函數DecrementPendingAndFinishIfNecessary調用了Logger.Info函數,這個函數使用了系統的StackTrace.CaptureStackTrace來擷取當前的呼叫堆疊。那麼為什麼這個函數StackTrace.CaptureStackTrace又會去構造它自己的對象呢?讓我們開啟我們程式的原始碼進一步分析。 分析和定位我們的原始碼

開啟我們的代碼並找到Logger.Info的實現,紅色的代碼正是驗證了我們上面的推理。在一些極端的形況下,StackTrace會建立失敗並扔出異常,這個異常恰好被後面的catch塊捕獲再次調用了Logger的函數,而這個函數會再次建立StackTrace類型的對象,繼續觸發異常導致了反覆的調用。

private static void WriteLine(Level level, string message){    try    {        if (0 == message.Length)        {            return;        }        StackTrace st = new StackTrace(); // 1. 這裡exception        string name = st.GetFrame(2).GetMethod().Name;        string prefix = string.Format("[{0}]@{1}", level, name);        message = prefix + "-" + message;    }    catch (Exception e)    {        Logger.Fatal("Faild in WriteLog,message:" + e.Message); // 2. 然後執行這裡    }}public static void Fatal(string message){    WriteLine(Level.Fatal, message); //3. 這裡繼續執行1, 1 繼續exception}

 

知道了原因,我們就可以修改代碼來修複了,最簡單的方法就是先去掉catch裡面的調用。

後續問題

那麼為什麼系統的StackTrack的GetStackFramesInternal會失敗呢?感興趣的同學可以嘗試反編譯命令來查看裡面的細節。

 

分享代碼,改變世界!

Windows Phone App的dump檔案執行個體分析-Stack Overflow

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.