Outline
如何獲得crash日志
如何解析crash日志
如何分析crash日志
1. iOS策略相關
2. 常見錯誤標識
3. 代碼bug
一、如何獲得crash日志
當一個iOS應用程序崩潰時,系統會創建一份crash日志保存在設備上。這份crash日志記錄著應用程序崩潰時的信息,通常包含著每個執行線程的棧調用信息(低內存閃退日志例外),對於開發人員定位問題很有幫助。
如果設備就在身邊,可以連接設備,打開Xcode – Window – Organizer,在左側面板中選擇Device Logs(可以選擇具體設備的Device Logs或者Library下所有設備的Device Logs),然後根據時間排序查看設備上的crash日志。這是開發、測試階段最經常采用的方式。
如果應用程序已經提交到App Store發佈,用戶已經安裝使用瞭,那麼開發者可以通過iTunes Connect(Manage Your Applications
– View Details – Crash Reports)獲取用戶的crash日志。不過這並不是100%有效的,而且大多數開發者並不依賴於此,因為這需要用戶設備同意上傳相關信息,詳情可參見iOS: Providing Apple with diagnostics and usage information摘要。
考慮到並不是所有iPhone用戶都允許自動發送診斷報告(crash日志),而且對於部分提交到Apple得crash日志,開發者還需要手動去拉取,然後找到對應的符號文件進行解析——這是一件很繁瑣的事情。所以實際項目開發中,通常接入現有的crash收集工具(參考1,參考2),或者自己編寫一個進行自動化收集、解析和統計匯總。
二、如何解析crash日志
當獲得一份crash日志時,我們需要將初始展示的十六進制地址等原始信息映射為源代碼級別的方法名稱和代碼行數,使其對開發人員可讀。這個過程稱為符號化解析。要成功地符號化解析一份crash日志,我們需要有對應的應用程序二進制文件以及符號(.dSYM)文件。
如果處於開發調試階段,通常Xcode都能匹配到crash日志對應的二進制文件和符號文件,所以能夠幫我們自動解析。
如果處於測試階段,測試人員已經安裝瞭不同的版本(比如alpha、beta版本),那麼需要保存好對應版本的二進制文件和符號文件,以便在應用程序崩潰時對crash日志進行解析。對於這種場景下產生的crash日志,隻需要將.crash文件、.app文件和.dSYM文件三者放在同一個目錄下,然後將.crash文件拖放到Xcode – Window – Organizer中左側面板Library下的Device Logs中,即可進行解析。
如果要提交發佈,那麼我們通常會先執行Clean,再Build,最後通過Product – Archive來打包。這樣,Xcode會將二進制文件和符號文件歸檔在一起,可以通過Organizer中的Archives進行瀏覽。
這裡是一份關於如何解析crash日志的討論:https://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports 。
三、如何分析crash日志
在分析一份crash日志之前,如果開發人員對於常見的錯誤類型有所瞭解,那定是極好的。
crash日志的產生來源於兩種問題:違反iOS策略被幹掉,以及自身的代碼bug。
1. iOS策略
1.1 低內存閃退
前面提到大多數crash日志都包含著執行線程的棧調用信息,但是低內存閃退日志除外,這裡就先看看低內存閃退日志是什麼樣的。
我們使用Xcode 5和iOS 7的設備模擬一次低內存閃退,然後通過Organizer查看產生的crash日志,可以發現Process和Type都為Unknown:
而具體的日志內容如下:
vc/U57XEsOaxvtbQv8nS1NTaxLPQqb34s8y688Pmv7S1vaGwamV0dGlzb25lZKGx19bR+aOsse3D99Xi0Km9+LPMyrnTw7n9tuDE2rTmsbvW1da5wcujrLb4z9bU2s7Sw8e/tLW9tcTKx6Gwdm0tcGFnZXNob3J0YWdlobHX1tH5oaM8YnI+Cjxicj4KtbFpT1O87LLitb3E2rTmuf21zcqxo6zL/KOotcRWTc+1zbOjqbvht6Kz9rXNxNq05r6vuObNqNaqo6yzosrUu9jK1dK70KnE2rTmo7vI57n7x+m/9sO709C1w7W91+O5u7XEuMTJxqOsaU9Tu+HW1da5uvPMqNOm08PS1LvYytW4/LbgxNq05qO71+6686OsyOe5+8TatOa7ucrHsrvX46OsxMfDtNX91NrUy9DQtcTTptPDv8nE3LvhsbvW1da5tfShozxicj4Ky/nS1KOsztLDx7XE06bTw9OmuMO6z8DttdjP7NOmz7XNs8XXs/bAtLXEtc3E2rTmvq+45s2o1qqjrLbU0rvQqbu6tObK/b7dus2/ydbY0MK0tL2otcS21M/zvfjQ0MrNt8WjrM2syrHSqrHcw+Kz9s/WxNq05tC5wra1yM7KzOKhozxicj4KPGJyPgq1zcTatObJwc3LysfTyWlPU7LfwtS+9rao1tXWudOm08OzzNDy1MvQ0LXEo6zNrNH5u/nT2mlPU7LfwtS1xLu509BXYXRjaGRvZ7OsyrG6zdPDu6fHv9bGzcuz9qGjPGJyPgo8YnI+CjxzdHJvbmc+MS4yIFdhdGNoZG9ns6zKsTwvc3Ryb25nPjxicj4KQXBwbGW1xGlPUyBEZXZlbG9wZXIgTGlicmFyec341b7Jz6OsPHU+UUExNjkzPC91Ps7EtbXW0MPoyvbBy1dhdGNoZG9nu/rWxqOssPzAqMn60Kezob6wus2x7c/WoaPI57n7ztLDx7XE06bTw7PM0PK21NK70KnM2LaotcRVScrCvP6jqLHIyOfG9LavoaK50sbwoaK71ri0oaK94cr4o6nP7NOmsru8sMqxo6xXYXRjaGRvZ7vhsNHO0sPHtcTTptPDs8zQ8rjJtfSjrLKiyfqzydK7t93P7NOmtcRjcmFzaLGouOahozxicj4KPGJyPgrV4rfdY3Jhc2ixqLjmtcTT0Mik1q60ptTa09rS7LOjtPrC66O6obAweDhiYWRmMDBkobGjrLy0obBhdGUgYmFkIGZvb2ShsaGjPGJyPgrI57n7y7XM2LaotcRVScrCvP6xyL3Ps+nP86OsxMfDtNPDtPrC68C01rG908Poyva1xLuwo6y21NOmtcS+zcrHo6i0tL2o0ru49rmks8zKsVhjb2Rl19S2r8n6s8m1xKOpVUlBcHBsaWNhdGlvbkRlbGVnYXRltcS8uLj2t723qKO6PGJyPgo8YnI+CjxpbWcgc3JjPQ==”/uploadfile/Collfiles/20140210/20140210133630184.jpg” alt=”\”>
所以當遇到Watchdog日志時,可以檢查下上圖幾個方法是否有比較重的阻塞UI的動作。
QA1693舉的例子是在主線程進行同步網絡請求。如果我們是在公司的Wifi環境下使用則一切順利,但當應用程序發佈出去面向很大范圍的用戶,在各種網絡環境下運行,則不可避免地會出現一片Watchdog超時報告。
另一種可能出現問題的場景就是數據量比較大的情況下進行的數據庫版本遷移(同樣是在主線程上),這也是促使我寫這篇總結的一個直接因素。
1.3 用戶強制退出
一看到“用戶強制退出”,首先可能想到的雙擊Home鍵,然後關閉應用程序。不過這種場景是不會產生crash日志的,因為雙擊Home鍵後,所有的應用程序都處於後臺狀態,而iOS隨時都有可能關閉後臺進程,所以這種場景沒有crash日志。
另一種場景是用戶同時按住電源鍵和Home鍵,讓iPhone重啟。這種場景會產生日志(僅驗證過一次),但並不針對特定應用程序。
這裡指的“用戶強制退出”場景,是稍微比較復雜點的操作:先按住電源鍵,直到出現“滑動關機”的界面時,再按住Home鍵,這時候當前應用程序會被終止掉,並且產生一份相應事件的crash日志。
通常,用戶應該是遇到應用程序卡死,並且影響到瞭iOS響應,才會進行這樣的操作——不過感覺這操作好高級,所以這樣的crash日志應該比較少見。
2. 常見錯誤標識
2.1 Exception codes
上面“用戶強制退出”的crash日志中的Exception Codes是“0xdeadfa11”,再上面“Watchdog超時”的crash日志中的Exception Codes是“0x8badf00d”,這些都是特有的Exception codes。
根據官方文檔描述,至少有以下幾種特定異常代碼:
0x8badf00d錯誤碼:Watchdog超時,意為“ate bad food”。
0xdeadfa11錯誤碼:用戶強制退出,意為“dead fall”。
0xbaaaaaad錯誤碼:用戶按住Home鍵和音量鍵,獲取當前內存狀態,不代表崩潰。
Android),如果有興趣到阿裡巴巴(杭州)工作,可以聯系我,或者直接把簡歷發到 siqin.ljp(at)taobao.com。