本文分析了一份標(biāo)準(zhǔn)的iOS應(yīng)用程序的Crash報(bào)告,它通常由以下6個(gè)部分組成。
報(bào)告頭(Header)
報(bào)告頭包含了應(yīng)用程序以其運(yùn)行環(huán)境的一些基本信息,下面是報(bào)告頭的一個(gè)例子。
復(fù)制代碼
Incident Identifier: E6EBC860-0222-4B82-BF7A-2B1C26BE1E85
CrashReporter Key: 6196484647b3431a9bc2833c19422539549f3dbe
Hardware Model: iPhone6,1
Process: TheElements [4637]
Path: /private/var/mobile/Containers/Bundle/Application/5A9E4FC2-D03B-4E19-9A91-104A0D0C1D44/TheElements.app/TheElements
Identifier: com.example.apple-samplecode.TheElements
Version: 1.12
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2015-04-06 09:14:08.775 -0700
Launch Time: 2015-04-06 09:14:08.597 -0700OS
Version: iOS 8.1.3 (12B466)
Report Version: 105
異常代碼(Exception Codes)
異常代碼可能包含異常類型(Exception Type)、異常子類型(Exception Subtype)、處理器的詳細(xì)異常代碼(processor-specific Exception Codes)和其它能提供更多Crash信息的字段,最后一個(gè)字段列出了觸發(fā)Crash的線程索引。下面是異常代碼的示例。
復(fù)制代碼
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 0
常見(jiàn)的異常類型有以下幾種。
-
Bad Memory Access [EXC_BAD_ACCESS // SIGSEGV // SIGBUS]
此類型的Excpetion是最常見(jiàn)的Crash,通常由訪問(wèn)了無(wú)效的內(nèi)存導(dǎo)致。
SIGSEGV:訪問(wèn)了無(wú)效地址,沒(méi)有[物理內(nèi)存]對(duì)應(yīng)該地址,通常由于重復(fù)釋放對(duì)象導(dǎo)致。
SIGBUS:總線錯(cuò)誤,與 SIGSEGV 不同的是,SIGBUS 訪問(wèn)的是[有效地址]),但總線訪問(wèn)異常,通常是訪問(wèn)了未對(duì)齊的數(shù)據(jù)。
SEGV:代表無(wú)效內(nèi)存地址,比如空指針、未初始化指針、棧溢出等。 -
Abnormal Exit [EXC_CRASH // SIGABRT]
進(jìn)程異常退出,造成Crash通常是因?yàn)槲床东@到Objective-C/C++的異常。
SIGABRT:收到Abort信號(hào)退出,通常Foundation庫(kù)中的容器為了保護(hù)狀態(tài)正常會(huì)做一些檢測(cè),例如插入nil到數(shù)組中等會(huì)遇到此類錯(cuò)誤。 -
Trace Trap [EXC_BREAKPOINT // SIGTRAP]
這個(gè)異常是為了讓一個(gè)附加的調(diào)試器有機(jī)會(huì)在執(zhí)行過(guò)程中的某個(gè)特定時(shí)刻中斷進(jìn)程,我們可以在代碼里面添加__builtin_trap()方法手動(dòng)觸發(fā)這個(gè)異常。如果沒(méi)有附加調(diào)試器,則會(huì)生成crash文件。
較低級(jí)別的庫(kù)(例如libdispatch)會(huì)在遇到致命錯(cuò)誤時(shí)捕獲該進(jìn)程。
swift代碼在遇到下面2種情況的時(shí)候也會(huì)拋出這個(gè)異常:
一個(gè)非可選類型的值為nil
錯(cuò)誤的強(qiáng)制類型轉(zhuǎn)換,如把NSString轉(zhuǎn)換為NSDate等等。 -
Illegal Instruction [EXC_BAD_INSTRUCTION // SIGILL]
程序嘗試的去執(zhí)行一個(gè)非法的或者沒(méi)有定義的指令。如果配置的函數(shù)地址有問(wèn)題,進(jìn)程在執(zhí)行函數(shù)跳轉(zhuǎn)的時(shí)候,就會(huì)發(fā)生這個(gè)crash。 -
Quit [SIGQUIT]
該進(jìn)程在具有管理其生命周期的權(quán)限的另一進(jìn)程的請(qǐng)求下終止。 SIGQUIT并不意味著進(jìn)程崩潰,但是可以說(shuō)明該進(jìn)程存在一些問(wèn)題。
比如在iOS中,第三方鍵盤應(yīng)用可能在在其他APP中被喚起,但是如果鍵盤應(yīng)用需要很長(zhǎng)的時(shí)間去加載,則會(huì)被強(qiáng)制退出。 -
Killed [SIGKILL]
進(jìn)程被系統(tǒng)強(qiáng)制結(jié)束,通過(guò)查看Termination Reason找到crash信息。Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
The exception code0x8badf00dindicates that an application has been terminated by iOS because a watchdog timeout occurred. The application took too long to launch, terminate, or respond to system events. One common cause of this is doing synchronous networking on the main thread.
Whatever operation is onThread 0needs to be moved to a background thread, or processed differently, so that it does not block the main thread.
異常代碼 0x8badf00d 指示應(yīng)用程序已終止的 iOS 因?yàn)榭撮T狗超時(shí)發(fā)生。應(yīng)用程序時(shí)間太長(zhǎng),啟動(dòng)、 終止,或?qū)ο到y(tǒng)事件作出響應(yīng)。一個(gè)常見(jiàn)的原因做在主線程上的同步聯(lián)網(wǎng) - 其它異常類型有些異常類型沒(méi)有被命名,以16進(jìn)制數(shù)字表示。
0xbaaaaaad:意味著該Crash log并非一個(gè)真正的Crash,它僅僅只是包含了整個(gè)系統(tǒng)某一時(shí)刻的運(yùn)行狀態(tài),由用戶同時(shí)按Home鍵和音量鍵觸發(fā)。
0xbad22222:當(dāng)VoIP程序在后臺(tái)太過(guò)頻繁的激活時(shí),系統(tǒng)可能會(huì)終止此類程序。
0x8badf00d:程序啟動(dòng)或者恢復(fù)時(shí)間過(guò)長(zhǎng)被watch dog終止。0xc00010ff:程序執(zhí)行大量耗費(fèi)CPU和GPU的運(yùn)算,導(dǎo)致設(shè)備過(guò)熱,觸發(fā)系統(tǒng)過(guò)熱保護(hù)被系統(tǒng)終止。
0xdead10cc:程序退到后臺(tái)時(shí)還占用系統(tǒng)資源(如通訊錄)被系統(tǒng)終止。
0xdeadfa11:程序無(wú)響應(yīng)用戶強(qiáng)制退出。當(dāng)用戶長(zhǎng)按電源鍵,直到屏幕出現(xiàn)關(guān)機(jī)確認(rèn)畫面后再長(zhǎng)按Home鍵,將強(qiáng)制退出應(yīng)用。我們可以合理認(rèn)為用戶這么做的原因是應(yīng)用程序沒(méi)有響應(yīng)。
關(guān)于符號(hào)化:http://blog.csdn.net/rainbowfactory/article/details/73332735
關(guān)于dsym文件:http://www.cocoachina.com/ios/20141219/10694.html
ips文件中各個(gè)線程都是地址,看不到具體的類和方法,需要通過(guò)解密,方法如下。
方式一
1.isp文件改為.crash文件

2.打包時(shí)產(chǎn)生的xcarchive包

3.連接設(shè)備使用log

4.把.crash文件丟進(jìn)alllogs里

可以看到最終崩潰在28線程中的UACacheManager中。
方式二
使用dSYM工具
將 dSYM 拉入窗口的第一部分,
雙擊 dSYM 名稱后,右邊顯示可選archive編譯類型,
UUID 是自動(dòng)的,請(qǐng)對(duì)好類型,
根據(jù)閃退信息填入對(duì)應(yīng)的內(nèi)存地址和Slide Address,
點(diǎn)擊分析按鈕,就會(huì)顯示可能錯(cuò)誤的地方了
方式三
1、找到symbolicatecrash
find /Applications/Xcode.app -name symbolicatecrash -type f
稍等一會(huì)就會(huì)有路徑輸出,這個(gè)路徑就是symbolicatecrash的路徑
2、用命令將symbolicatecrash拷貝到crash文件夾里面
3、將ips文件改為.crash文件導(dǎo)入,ipa包解壓后的app文件導(dǎo)入,.dSYM文件導(dǎo)入
4、生成解析后文件
./symbolicatecrash .crash路徑 .dSYM路徑 >log.crash
5、這時(shí)候終端有可能會(huì)出現(xiàn):
Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 69.
輸入命令:
export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"