本文分析了一份標準的iOS應用程序的Crash報告,它通常由以下6個部分組成。
1. 報告頭(Header)
報告頭包含了應用程序以其運行環境的一些基本信息,下面是報告頭的一個例子。
復制代碼
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 -0700
OS Version: iOS 8.1.3 (12B466)
Report Version: 105
2. 異常代碼(Exception Codes)
異常代碼可能包含異常類型(Exception Type)、異常子類型(Exception Subtype)、處理器的詳細異常代碼(processor-specific Exception Codes)和其它能提供更多Crash信息的字段,最后一個字段列出了觸發Crash的線程索引。下面是異常代碼的示例。
復制代碼
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 0
常見的異常類型有以下幾種。
a. Bad Memory Access [EXC_BAD_ACCESS // SIGSEGV // SIGBUS]
此類型的Excpetion是最常見的Crash,通常由訪問了無效的內存導致。
SIGSEGV:訪問了無效地址,沒有物理內存對應該地址,通常由于重復釋放對象導致。
SIGBUS:總線錯誤,與 SIGSEGV 不同的是,SIGBUS 訪問的是有效地址,但總線訪問異常,通常是訪問了未對齊的數據。
SEGV:代表無效內存地址,比如空指針、未初始化指針、棧溢出等。
b. Abnormal Exit [EXC_CRASH // SIGABRT]
進程異常退出,造成Crash通常是因為未捕獲到Objective-C/C++的異常。
SIGABRT:收到Abort信號退出,通常Foundation庫中的容器為了保護狀態正常會做一些檢測,例如插入nil到數組中等會遇到此類錯誤。
c. 其它異常類型
有些異常類型沒有被命名,以16進制數字表示。
0xbaaaaaad:意味著該Crash log并非一個真正的Crash,它僅僅只是包含了整個系統某一時刻的運行狀態,由用戶同時按Home鍵和音量鍵觸發。
0xbad22222:當VoIP程序在后臺太過頻繁的激活時,系統可能會終止此類程序。
0x8badf00d:程序啟動或者恢復時間過長被watch dog終止。
0xc00010ff:程序執行大量耗費CPU和GPU的運算,導致設備過熱,觸發系統過熱保護被系統終止。
0xdead10cc:程序退到后臺時還占用系統資源(如通訊錄)被系統終止。
0xdeadfa11:程序無響應用戶強制退出。當用戶長按電源鍵,直到屏幕出現關機確認畫面后再長按Home鍵,將強制退出應用。我們可以合理認為用戶這么做的原因是應用程序沒有響應。
3. 應用詳情(Application Specific Information)
有些Crash出現時,會產生額外的信息,這些信息能幫助用戶更好地了解應用程序終止時的運行環境。示例如下。
復制代碼
Application Specific Information:
MyApp[134] was suspended with locked system files:
/private/var/mobile/Library/AddressBook/AddressBook.sqlitedb
4. 回溯(Backtrace)
這部分列出了發生Crash時線程的調用棧。示例如下。
復制代碼
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0? TheElements? ? ? ? ? ? ? 0x0000000100063fdc -[AtomicElementViewController myTransitionDidStop:finished:context:] (AtomicElementViewController.m:201)
1? UIKit? ? ? ? ? ? ? ? ? ? 0x000000018ca5c2ec -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 184
2? UIKit? ? ? ? ? ? ? ? ? ? 0x000000018ca5c1f4 -[UIViewAnimationState animationDidStop:finished:] + 100
3? QuartzCore? ? ? ? ? ? ? ? 0x000000018c380f60 CA::Layer::run_animation_callbacks(void*) + 292
4? libdispatch.dylib? ? ? ? 0x0000000198fb9368 _dispatch_client_callout + 12
5? libdispatch.dylib? ? ? ? 0x0000000198fbd97c _dispatch_main_queue_callback_4CF + 928
6? CoreFoundation? ? ? ? ? ? 0x000000018822dfa0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
7? CoreFoundation? ? ? ? ? ? 0x000000018822c048 __CFRunLoopRun + 1488
8? CoreFoundation? ? ? ? ? ? 0x00000001881590a0 CFRunLoopRunSpecific + 392
9? GraphicsServices? ? ? ? ? 0x00000001912fb5a0 GSEventRunModal + 164
10? UIKit? ? ? ? ? ? ? ? ? ? 0x000000018ca8aaa0 UIApplicationMain + 1484
11? TheElements? ? ? ? ? ? ? 0x000000010005d800 main (main.m:55)
12? libdyld.dylib? ? ? ? ? ? 0x0000000198fe2a04 start + 0
Thread 1 name: Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0? libsystem_kernel.dylib? ? 0x00000001990e0c94 kevent64 + 8
1? libdispatch.dylib? ? ? ? 0x0000000198fc897c _dispatch_mgr_invoke + 272
2? libdispatch.dylib? ? ? ? 0x0000000198fbb3b0 _dispatch_mgr_thread + 48
...
5. 線程狀態(Thread State)
這部分列出了發生Crash的線程的狀態,即寄存器和寄存器的值。示例如下。
復制代碼
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x0000000000000000? x1: 0x0000000000000000? x2: 0x0000000000000000? x3: 0x00000001995f8020
x4: 0x0000000000000000? x5: 0x0000000000000001? x6: 0x0000000000000000? x7: 0x0000000000000000
x8: 0x0000000000000000? x9: 0x0000000000000015? x10: 0x0000000199601df0? x11: 0x0000000b0000000f
x12: 0x00000001741e8700? x13: 0x000001a5995f5779? x14: 0x0000000000000000? x15: 0x0000000044000000
x16: 0x00000001989724d8? x17: 0x0000000188176370? x18: 0x0000000000000000? x19: 0x00000001701dda60
x20: 0x0000000000000001? x21: 0x0000000136606e20? x22: 0x00000001000f6238? x23: 0x0000000000000000
x24: 0x000000019cc640a8? x25: 0x0000000000000020? x26: 0x0000000000000000? x27: 0x0000000000000000
x28: 0x000000019cc577c0? fp: 0x000000016fd1a8d0? lr: 0x00000001000effcc
sp: 0x000000016fd1a860? pc: 0x00000001000effdc cpsr: 0x60000000
6. 二進制映像(Binary Images)
這部分列出了當Crash發生時被裝載進進程內存空間的依賴庫或者模塊。示例如下。
復制代碼
Binary Images:
0x100058000 - 0x10006bfff TheElements arm64 <77b672e2b9f53b0f95adbc4f68cb80d6> /var/mobile/Containers/Bundle/Application/CB86658C-F349-4C7A-B73B-CE3B4502D5A4/TheElements.app/TheElements
參考資料
a. 《Understanding and Analyzing iOS Application Crash Reports 》,iOS Crash分析官方文檔
b. 《iOS Crash文件的解析(一)》,一篇中文博客