[原文位址](http://www.jianshu.com/p/0b6f5148dab8)
序
在日常開發中,app難免會發生崩潰。簡單的崩潰還好說,複雜的崩潰就需要我們通過解析Crash檔案來分析了,解析Crash檔案在iOS開發中是比較常見的。
擷取崩潰資訊方式
在iOS中擷取崩潰資訊的方式有很多,比較常見的是使用友盟、雲測、百度等第三方分析工具,或者自己收集崩潰資訊并上傳公司伺服器。
下面列舉一些我們常用的崩潰分析方式:
- 使用友盟、雲測、百度等第三方崩潰統計工具。
- 自己實作應用内崩潰收集,并上傳伺服器。
- Xcode-Devices中直接檢視某個裝置的崩潰資訊。
- 使用蘋果提供的Crash崩潰收集服務。(少用)
收集崩潰資訊
蘋果給我們提供了異常處理的類,NSException類。這個類可以建立一個異常對象,也可以通過這個類擷取一個異常對象。
這個類中我們最常用的還是一個擷取崩潰資訊的C函數,我們可以通過這個函數在程式發生異常的時候收集這個異常。
// 将系統提供的擷取崩潰資訊函數寫在這個方法中,以保證在程式開始運作就具有擷取崩潰資訊的功能
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 将下面C函數的函數位址當做參數
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
return YES;
}
// 設定一個C函數,用來接收崩潰資訊
void UncaughtExceptionHandler(NSException *exception){
// 可以通過exception對象擷取一些崩潰資訊,我們就是通過這些崩潰資訊來進行解析的,例如下面的symbols數組就是我們的崩潰堆棧。
NSArray *symbols = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
}
我們也可以通過下面方法擷取崩潰統計的函數指針:
NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
dSYM 符号集
- 符号集是我們對ipa檔案進行打包之後,和.app檔案同級的字尾名為.dSYM的檔案,這個檔案必須使用Xcode進行打包才有。
- 每一個.dSYM檔案都有一個UUID,和.app檔案中的UUID對應,代表着是一個應用。而.dSYM檔案中每一條崩潰資訊也有一個單獨的UUID,用來和程式的UUID進行校對。
- 我們如果不使用.dSYM檔案擷取到的崩潰資訊都是不準确的。
- 符号集中存儲着檔案名、方法名、行号的資訊,是和可執行檔案的16進制函數位址對應的,通過分析崩潰的.Crash檔案可以準确知道具體的崩潰資訊。
我們每次Archive一個包之後,都會随之生成一個dSYM檔案。每次釋出一個版本,我們都需要備份這個檔案,以友善以後的調試。進行崩潰資訊符号化的時候,必須使用目前應用打包的電腦所生成的dSYM檔案,其他電腦生成的檔案可能會導緻分析不準确的問題。

Archive.png
當程式崩潰的時候,我們可以獲得到崩潰的錯誤堆棧,但是這個錯誤堆棧都是0x開頭的16進制位址,需要我們使用Xcode自帶的symbolicatecrash工具來将.Crash和.dSYM檔案進行符号化,就可以得到詳細崩潰的資訊。
崩潰分析
- 指令行解析Crash檔案
通過Mac自帶的指令行工具解析Crash檔案需要具備三個檔案
- symbolicatecrash,Xcode自帶的崩潰分析工具,使用這個工具可以更精确的定位崩潰所在的位置,将0x開頭的位址替換為響應的代碼和具體行數。
- 我們打包時産生的dSYM檔案。
- 崩潰時産生的Crash檔案,例如:*.crash。
我在解析崩潰資訊的時候,首先在桌面上建立一個Crash檔案夾,然後将.Crash、.dSYM、symbolicatecrash放在這個檔案夾中,這樣進入這個檔案夾下,直接一行指令就解決了。
symbolicatecrash我們可以在下面路徑下可以找到,我用的是Xcode7,其他版本Xcode路徑不一樣,請自行Google。
/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash
選中archive的版本右擊,選擇Show in Finder就可以選中archived 檔案然後顯示包内容,就可以找到dSYM檔案了。
dsym檔案位置.png
将.Crash、.dSYM、symbolicatecrash三個檔案都放在我們在桌面建立的Crash檔案夾中。
crash.png
進行解析的工作
開啟指令行工具,進入崩潰檔案夾crash中
cd /Users/自己MacPro上的名字/Desktop/崩潰檔案夾crash
使用指令解析Crash檔案,*号指的是具體的檔案名
./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash
如果上面指令不成功,使用指令檢查一下環境變量
xcode-select -print-path
傳回結果:
/Applications/Xcode.app/Contents/Developer/
如果不是上面的結果,需要使用下面指令設定一下導出的環境變量,然後重複上面解析的操作。(這一步很重要)
export DEVELOPER_DIR=/Applications/XCode.app/Contents/Developer
解析完成後會生成一個新的.Crash檔案,這個檔案中就是崩潰詳細資訊。圖中紅色标注的部分就是我們代碼崩潰的部分。
result.png
注意,以下情況不會有崩潰資訊産生:
- 記憶體通路錯誤(不是野指針錯誤)
- 低記憶體,當程式記憶體使用過多會造成系統低記憶體的問題,系統會将程式記憶體回收
- 因為某種原因觸發看門狗機制
通過Xcode檢視裝置崩潰資訊
除了上面的系統分析工具來進行分析,如果是我們自己直接使用手機連接配接崩潰或者崩潰之後連接配接手機,選擇window-> devices -> 選擇自己的手機 -> view device logs 就可以檢視我們的崩潰資訊了。
deviceLog.png
隻要手機上的應用是這台電腦安裝打包的,這樣的崩潰資訊系統已經為我們符号化好了,我們隻需要進去之後等一會就行(不要相信這裡面的進度重新整理,并不準确),如果還是沒有符号化完畢 ,我們選擇檔案,然後右擊選擇Re-Sysbomlicate就可以。
如果是使用其他電腦進行的打包,我們可以在這裡面将Crash檔案導出,自己通過指令行的方式進行解析。