iOS開發之Crash日誌獲取與分析
當在非除錯狀態下,我們用真機測試app,crash或者說閃退是一件很常見的事,最讓我們開發人員頭疼的是,自己在開發過程中總是不會遇到crash,安裝到別人的裝置,就出現了閃退崩潰現象。這種偶現的、概率比較低的閃退是最令人頭疼。
這時iOS crash log 派上用場了,程式的大多數crash都會記錄在使用者的手機中,獲取crash log的方法有兩種:
- 使用者把裝置連線到電腦上,開啟xcode-window,選中Devices-當前連線裝置-Device Log,就可以檢視所有當前裝置的crash log,這個時候開啟每一份crash的時候,發現這些檔案的部分地址都會被轉換成,類名,方法名和行號等。裝置上的日誌只用剛剛檢視過都會被同步到organizer種,在LIBRARY下的Device Log可以檢視。
- 如果你的應用已經上架,那麼開發者可以通過iTunes Connect(Manage Your Applications - View Details - Crash Reports)獲取使用者的crash日誌。不過這並不是100%有效的,而且大多數開發者並不依賴於此,因為這需要使用者裝置同意上傳相關資訊,詳情可參見iOS: Providing Apple with diagnostics and usage information摘要。
當上面方法都不行時,就是說在Devices看不到logs時,那就用下面的方法來獲取crash日誌檔案
裝置連線iTune,選擇裝置和mac同步檔案,然後儲存在手機裡的crash日誌檔案將會同步到電腦,目錄在
~/Library/Logs/CrashReporter/MobileDevice/xxx的 iPhone
如下圖,就是所有的crash檔案:
開啟crash日誌檔案,你會有點蒙圈,因為全都是十六進位制的資料
常見的Exception Type & Exception Code
1、Exception Type
1)EXC_BAD_ACCESS
此型別的Excpetion是我們最長碰到的Crash,通常用於訪問了不改訪問的記憶體導致。一般EXC_BAD_ACCESS後面的”()”還會帶有補充資訊。
SIGSEGV:通常由於重複釋放物件導致,這種型別在切換了ARC以後應該已經很少見到了。
SIGABRT: 收到Abort訊號退出,通常Foundation庫中的容器為了保護狀態正常會做一些檢測,例如插入nil到陣列中等會遇到此類錯誤。
SEGV:(Segmentation Violation),代表無效記憶體地址,比如空指標,未初始化指標,棧溢位等;
SIGBUS:匯流排錯誤,與 SIGSEGV 不同的是,SIGSEGV 訪問的是無效地址,而 SIGBUS 訪問的是有效地址,但匯流排訪問異常(如地址對齊問題)
SIGILL:嘗試執行非法的指令,可能不被識別或者沒有許可權
2)EXC_BAD_INSTRUCTION
此類異常通常由於執行緒執行非法指令導致
3)EXC_ARITHMETIC
除零錯誤會丟擲此類異常
2、Exception Code
0xbaaaaaad 此種類型的log意味著該Crash log並非一個真正的Crash,它僅僅只是包含了整個系統某一時刻的執行狀態。通常可以通過同時按Home鍵和音量鍵,可能由於使用者不小心觸發
0xbad22222當VOIP程式在後臺太過頻繁的啟用時,系統可能會終止此類程式
0x8badf00d這個前面已經介紹了,程式啟動或者恢復時間過長被watch dog終止
0xc00010ff程式執行大量耗費CPU和GPU的運算,導致裝置過熱,觸發系統過熱保護被系統終止
0xdead10cc程式退到後臺時還佔用系統資源,如通訊錄被系統終止
0xdeadfa11前面也提到過,程式無響應使用者強制關閉
其實,crash log裡關鍵的資訊就在backtrace,對linux有一定了解的相信對backtrace是有所瞭解的,其實Linux下常常利用backtrace追蹤函式呼叫堆疊以及定位段錯誤
那關鍵的來了,把Backtrace的十六進位制資料轉成我們能看懂的文字,這個過程我們稱之為符號化,那麼我們就一步一步講解
- 1.上述獲取到log後,我們首先找到相對應的.dSYM檔案,在哪呢?就在這個目錄裡: ~/Library/Developer/Xcode/Archives/
- 2.進入這個目錄後,可能會有多個archive檔案,找到對應時間的,然後右鍵顯示包內容,可以看到,xxx.app.dSYM檔案,如下圖:
- 3.然後再找到上述圖片Products/Applications/xxx.app檔案
- 4.將上面crash log檔案,xxx.app.dSYM和xxx.app檔案拷貝到同一個檔案裡
怎麼確定.dSYM和.app檔案是同一個編譯出來的呢?
開啟終端,使用命令檢視兩個檔案的uuid是否一致,一致則表示.dSYM檔案和.app檔案是相匹配的,命令如下:
dwarfdump –uuid xxx.app/xxx
dwarfdump –uuid xxx.app.dSYM/ (xxx為app name) 5.然後使用命令列工具symbolicatecrash來符號化crash log
怎麼找到symbolicatecrash呢?
其實symbolicatecrash工具是Xcode自帶的一個命令列工具,找它,當然是去xcode的安裝目錄咯
先到xcode安裝去,一層一層往下走 /Applications/Xcode.app/Contents/SharedFrameworks
這裡偷個懶不去找symbolicatecrash在哪個目錄了,直接輸入查詢命令來找find ./ -name “symbolicatecrash”,如下圖
到這個目錄去,把這個工具拷貝到和上述檔案同一個目錄
sudo cp symbolicatecrash ~/Desktop/xxxxx/xxx然後就開始符號化,執行命令:
./symbolicatecrash appName-2016-10-26-201420.crash appName.app.dSYM/ > xxxxx.log
(如果執行命令出現錯誤:Error: “DEVELOPER_DIR” is not defined at ./symbolicatecrash,請設定環境變數:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer;)
開啟日誌檔案,你會發現,backtrace就變成我們可以讀懂的程式碼方法和精準定位到了哪一行了,哈哈
太好用了,這樣就遇到偶現的閃退,我們就可以比較輕鬆的定位問題,最快的定位問題,最好解決問題。
######總結
總結一下,整個過程就是,獲取crash log -》找到相匹配的 app檔案 -》 獲取symbolicatecrash工具 -》 符號化crash檔案。希望這個對大家有所幫助。