當前位置:
首頁 > 最新 > iOS crash 日誌堆棧解析

iOS crash 日誌堆棧解析

日常開發中,我們難免遇到一些 crash。大部分情況下,Xcode 可以幫助我們找到問題所在,但也有些情況,Xcode 給我們反饋的是一些看不懂的地址,大大增加了我們分析問題的難度。

下面,就來介紹幾種能讓看不懂的地址,變得看的懂的方式。

symbolicatecrash

.dSYM 文件

dSYM 是保存十六進位函數地址映射信息的中轉文件,我們調試的 symbols 都會包含在這個文件中。每次編譯項目的時候都會生成一個新的 dSYM 文件,我們應該保存每個正式發布版本的 dSYM 文件,以備我們更好的調試問題。一般是在我們 Archives 時保存對應的版本文件的,裡面也有對應的.dSYM和.app文件。路徑為:

.dSYM文件默認在 debug 模式下是不生成的,我們去 Build Settings -> Debug Information Format 下,將DWARF修改為DWARF with dSYM File,再重新編譯下就能生成.dSYM文件了,直接去項目工程的Products目錄下找就行。

symbols 又是什麼呢?

引用 《程序員的自我修養》中的解釋:

在鏈接中,我們將函數和變數統稱為符號(Symbol),函數名或變數名就是符號名(Symbol Name)。我們可以將符號看作是鏈接中的粘合劑,整個鏈接過程正是基於符號才能夠正確完成。

所以,所謂的 symbols 就是函數名變數名

找到 symbolicatecrash

symbolicatecrash是 Xcode 自帶的 crash 日誌分析工具,我們需要先找到它:

執行完後會返回幾個路徑,我的是:

我們到這個路徑下把symbolicatecrash拷貝出來,放到一個文件夾下。

拿到 crash 日誌文件

我們可以隨便寫段強制 crash 的代碼:

接著用真機打個包。打好包之後,不要用 Xcode build,直接用打好的包運行我們能導致 crash 的代碼,這樣就生成好.crash日誌文件了。

之後,我們去 Xcode -> Window -> Devices and Simulators 或者快捷鍵Command + Shift + 2

找到對應時間點的 .crash 文件,右擊 Export Log。

拿到 .app 文件

.app文件可以使用真機編譯下,去 項目Products目錄下獲取,也可以去 Archives 目錄下獲取。

符號解析

利用 dSYM

將.dSYM、.crash及symbolicatecrash放到同一個文件下,執行命令:

./symbolicatecrash .crash文件路徑 .dSYM文件路徑 > 名字.crash

利用 app

將.app、.crash及symbolicatecrash放到同一個文件下,執行命令:

./symbolicatecrash .crash文件路徑 .app/appName 路徑 > 名字.crash

可能會報錯誤:

執行下命令就行:

然後再重新生成下新的.crash文件就行。

我們可以對比下沒有符號化和符號化的文件,下面是我自己測試的例子,iPhone5 iOS 10.2, 可能會有所不同:

問題也能看出來,但是因為第三行(DreamDemo)並沒有符號化,導致我們並不確定具體調用位置

再來看看符號化之後的:

可以發現,第三行被解析出來了,這樣我們就能很清晰的知道具體的頁面了。

使用命令行工具 atos

symbolicatecrash 可以幫助我們很好的分析 crash 日誌,但是有它的局限性 --- 不夠靈活。我們需要symbolicatecrash、.crash及.dSYM三個文件才能解析。

相對於 symbolicatecrash,atos命令更加靈活,特別是你需要對不同渠道的 crash 文件,寫一個自動化的分析腳本的時候,這個方法就極其有用。

但是這種方式也有個不方便的地方:一個線上的 App,用戶使用的版本存在差異,而每個版本所對應的.dSYM都是不同的。必須確保.crash和.dSYM文件是匹配的,才能正確符號化,匹配的條件就是它們的 UUID 一致。 在這之前,先介紹下 UUID:

什麼是 UUID ?

UUID 是由一組 32 位數的十六進位數字所構成。每一個可執行程序都有一個 build UUID 唯一標識。.crash日誌包含發生 crash 的這個應用的 build UUID 以及 crash 發生時,應用載入的所有庫文件的 build UUID。

獲取 UUID

.crash UUID

執行命令:

輸出:

看到上面的輸出d009f8671129397a8aab9cb2b8e506ff就是DreamDemo項目的 UUID。

.dSYM UUID

執行命令:

輸出:

執行命令:

輸出:

可以發現這兩個文件的 UUID 是相同的,也就是匹配的,只有滿足這種條件,才能正確的解析!

atos 解析

我們現回顧下未解析前的堆棧:

執行命令:

接著輸入0x0008088e地址,終端輸出如下:

可以發現,正確的解析出來了!

除了搭配.dSYM文件,我們也可以使用.app文件來解析

執行命令:

xcrun atos -o DreamDemo.app/DreamDemo -arch armv7 -l 0x7c000

同樣輸入 0x0008088e 地址,效果是一樣的。

工具

直接操作atos命令畢竟是有點不方便,GitHub 上有個工具,可以輔助我們解析dSYMTools,這是個 Mac 客戶端,界面長這樣:

使用起來也很方便,我們只需要把對應的dSYM文件拖進去,它會自動識別 UUID。我們對應的輸入參數地址就行:

系統庫的符號化解析

細心的人可以發現,我們上面的解析都是針對DreamDemo,這個自己的項目的。其實很多系統方法的堆棧之所以能解析出來,是因為已經有了系統庫的符號化文件,存放目錄如下:

這些庫的版本都是和.crash文件中是對應的:

一旦我把這個10.2 (14C5077b)系統的符號化庫刪掉,.crash文件就會變成這樣:

Last Exception Backtrace:

可以明顯的發現,系統庫的堆棧變成了一堆地址。

新版本,每當我們手機連上 Xcode 時,都會把當前版本的系統符號庫自動導入到/用戶/用戶名稱xxx/資源庫/Developer/Xcode/iOS DeviceSupport目錄下。但是 iOS 版本那麼多,之前舊的系統符號庫該怎麼獲取呢?有人已經整理好了iOS-System-Symbols,我們只需要根據.crash文件的版本信息,下載對應的系統符號化文件到目錄下即可。

總結

利用symbolicatecrash解析,可以將整個.crash日誌堆棧解析,但是由於依賴symbolicatecrash、.crash以及.dSYM三個文件,或者.app、.crash及symbolicatecrash三個文件,導致不太靈活。

利用atos命令只需要.crash和.dSYM,或者.crash和.app,知道對應的堆棧地址,就能解析,方便自動化腳本分析,但是 crash 堆棧可能需要自己實現收集。

參考

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Cocoa開發者社區 的精彩文章:

被遺棄的線程
又要跳票!蘋果跨平台應用推遲到2019年問世

TAG:Cocoa開發者社區 |