分析Crash 日誌
1、Header
Incident Identifier: B6FD1E8E-B39F-430B-ADDE-FC3A45ED368C
CrashReporter Key: f04e68ec62d3c66057628c9ba9839e30d55937dc
Hardware Model: iPad6,8
Process: TheElements [303]
Path: /private/var/containers/Bundle/Application/888C1FA2-3666-4AE2-9E8E-62E2F787DEC1/TheElements.app/TheElements
Identifier: com.example.apple-samplecode.TheElements
Version: 1.12
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.example.apple-samplecode.TheElements [402]
Date/Time: 2016-08-22 10:43:07.5806 -0700
Launch Time: 2016-08-22 10:43:01.0293 -0700
OS Version: iPhone OS 10.0 (14A5345a)
Report Version: 104
Incident Identifier:crash日誌的標示。
CrashReporter Key:設備標誌符,同一個設備設備的兩份日誌,該標誌相同。
Beta Identifier:崩潰應用程序的設備和供應商組合的唯一標識符。 來自同一供應商和同一設備的兩個應用程序報告將包含相同的值。 此字段僅存在於爲通過TestFlight分發的應用程序生成的崩潰報告中,並替換CrashReporter Key字段。
Process:崩潰進程的可執行文件名。 這與應用程序的信息屬性列表中的CFBundleExecutable鍵的值匹配。
Version:崩潰的進程版本。 此字段的值是崩潰的應用程序的CFBundleVersion和CFBundleVersionString的串聯。
Code Type:崩潰的進程的目標體系結構。 這將是ARM-64,ARM,x86-64或x86之一。
Role:終止時分配給進程的task_role。
OS Version:發生崩潰的操作系統版本,包括內部版本號。
2、Exception Information
下面將列出了Mach異常類型和相關字段,這些字段提供的信息與崩潰性質有關。 但在崩潰報告中並非所有字段都會出現。
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
上面是一個Objective-C異常引起的crash日誌
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]
Triggered by Thread: 0
上面是引用NULL指針引起的crash日誌
Exception Codes:有關異常的處理器特定信息,編碼爲一個或多個64位十六進制數。通常,此字段將不存在,因爲Crash Reporter會解析異常代碼以將其作爲人類可讀的描述呈現在其他字段中。
Exception Subtype:異常代碼的人類可讀名稱。
Exception Message:從異常代碼中提取的其他人類可讀信息。
Exception Note:非特定於一種異常類型的附加信息。如果此字段包含SIMULATED(這不是崩潰),則該進程不會崩潰,但是在系統請求(通常是監視程序)時被殺死。
Termination Reason:終止進程時指定的退出原因信息。進程內部和外部的關鍵系統組件將在遇到致命錯誤(例如,錯誤的代碼簽名,缺少的依賴庫或在沒有適當授權的情況下訪問隱私敏感信息)時終止該進程。 macOS Sierra,iOS 10,watchOS 3和tvOS 10採用了新的基礎設施來記錄這些錯誤,這些操作系統生成的崩潰報告列出了終止原因字段中的錯誤消息。
Triggered by Thread:發生異常的線程。
3、常見的異常
-
Bad Memory Access【EXC_BAD_ACCESS // SIGSEGV // SIGBUS】
當進程去訪問無效的內存或者去寫入只讀存儲器,此時Exception SubType字段包含kern_return_t錯誤描述和訪問的錯誤的內存地址。
- EXC_BAD_ACCESS:訪問了不該訪問的內存,一般該類型後面還會有提示,例如野指針造成的錯誤在Xcode中通常表現爲:Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)
- SIGSEGV:小編沒有遇到過,網上有人說時重複釋放對象造成的、又有人說時試圖訪問未分配給對象的內存造成的~
- SIGBUS:非法地址, 包括內存地址對齊(alignment)出錯。比如訪問一個四個字長的整數, 但其地址不是4的倍數。它與SIGSEGV的區別在於,後者是由於對合法存儲地址的非法訪問觸發的
debug技巧
- 如果在堆棧的上部出現objc_msgSend或者objc_release,則說明該進程在試圖給已釋放的對象發消息,可使用Zombies Instrument幫助調試
- 如果在堆棧的上部出現gpus_ReturnNotPermittedKillClient,則說明進程在後臺渲染OpenGL ES 或Metal。
- 使用Address Sanitizer檢測app,address Sanitizer在編譯咱們的代碼時增加了額外的內存檢測
-
ABnormal Exit【EXC_CRASH // SICABRT】
該進程異常退出。 最常見原因是**未被捕獲的Objective-C / C ++異常以及對abort()**的調用。
如果App Extensions花費太多時間進行初始化(看門狗終止),則會以此異常類型終止。 如果由於啓動時掛起而導致擴展名被終止,則生成的崩潰報告的Exception Subtype將爲LAUNCH_HANG。 因爲擴展沒有main函數,所以花在初始化上的任何時間都發生在擴展和依賴庫中的靜態構造函數和+ load方法中。 你應該儘可能地推遲這項工作。
SIGABRT: 收到Abort信號退出, 通常Foundtion庫中的容器爲了保護狀態正常會做一些檢測, 例如插入nil到數據中等會遇到此類錯誤.
- Trace Trap [EXC_BREAKPOINT // SIGTRAP]
與異常退出類似,此異常是在使用debugger時在其執行的特定點中斷進程。可以使用**__builtin_trap()**函數在代碼中觸發此異常。如果未附加調試器,則終止該過程並生成崩潰報告。
使用較低級別的庫(例如libdispatch)時在遇到致命錯誤時捕獲該進程。有關錯誤的其他信息可以在崩潰報告的“其他診斷信息”部分或設備的控制檯中看到。還有就是Swift代碼運行時出錯以此異常類型終止,例如:具有nil值的非可選類型,強制類型轉換失敗
SIGTRAP 由斷點指令或其它trap指令產生
-
**Illegal Instruction **【EXC_BAD_INSTRUCTION (SIGILL)】
SIGILL 執行了非法指令. 通常是因爲可執行文件本身出現錯誤, 或者試圖執行數據段. 堆棧溢出時也有可能產生這個信號
-
**Quit **【SIGQUIT】
SIGQUIT 進程在因收到SIGQUIT退出時會產生coredump文件, 在這個意義上類似於一個程序錯誤信號。
- Killed 【SIGKILL】
此異常是進程在進行系統請求是產生的,一般是watchOS產生較多
SIGILL 執行了非法指令. 通常是因爲可執行文件本身出現錯誤, 或者試圖執行數據段. 堆棧溢出時也有可能產生這個信號。
等等,以上的說明大部分來自於官網,自己遇到的比較少。
3、堆棧
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 TheElements 0x000000010006bc20 -[AtomicElementViewController myTransitionDidStop:finished:context:] (AtomicElementViewController.m:203)
1 UIKit 0x0000000194cef0f0 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
2 UIKit 0x0000000194ceef30 -[UIViewAnimationState animationDidStop:finished:] + 160
3 QuartzCore 0x0000000192178404 CA::Layer::run_animation_callbacks(void*) + 260
4 libdispatch.dylib 0x000000018dd6d1c0 _dispatch_client_callout + 16
第一行列出了線程號和當前正在執行的調度隊列的標識符。
其餘行列出了有關回溯中各個堆棧幀的詳細信息。 從左到右:
- 第一豎列:堆棧幀號。 堆棧幀以調用順序呈現,其中第0幀是進程暫停時執行的函數。 第1幀是第0幀函數調用的函數,依此類推。
- 第二豎列:堆棧幀的執行函數所在的二進制文件的名稱。
- 第三豎列:對於第0幀,進程停止時執行的機器指令的地址。 對於剩餘的堆棧幀,當控制返回到堆棧幀時將下一次執行的機器指令的地址。
- 第四豎列:在符號化崩潰報告中,堆棧框架中函數的方法名稱。
4、異常
(1)Exception
數組的越界訪問、改變不可改變的對象、沒有實現要求實現的協議等等都會造成異常
注意:給已銷燬的對象發送消息可能不是crash,而是NSInvalidArgumentException,這時可在堆棧中查看是否有
[NSObject(NSObject) doesNotRecognizeSelector:]
,可以在提交自己程序前使用Zombies檢測一下。
(2)Last Exception Backtrace
如果未捕獲到異常,它被一個名爲uncaught exception handler的函數攔截。 對於未捕獲的異常,處理程序將異常消息記錄到設備的控制檯,然後終止該進程。 在Last Exception Backtrace部分下,只將異常回溯寫入生成的崩潰報告,如清單10所示。崩潰報告中省略了異常消息。 如果您收到帶有Last Exception Backtrace的崩潰報告,您應該從原始設備獲取控制檯日誌,以便更好地瞭解導致異常的條件。
相關文檔
如果想查看如何使用Zombies模板工具來修復內存釋放的crash,可以查看Eradicating Zombies with the Zombies Trace Template 。
如果想查看應用歸檔的信息,請參考 App Distribution Guide 。
如果想了解關於crash logs的解讀,請參考Understanding Crash Reports on iPhone OS WWDC 2010 Session 。
如果對異常NSException不瞭解,可以點擊查看NSException的介紹。
https://www.jianshu.com/p/8a46e78a450b
5、例子
工作中突然領導發給的crash日誌,說其他組認爲可能是你之前寫的業務引起的carsh日誌,讓你看看,你能怎麼辦,當然要看了,如下圖
分析Crash 日誌
1、Header
Incident Identifier: B6FD1E8E-B39F-430B-ADDE-FC3A45ED368C
CrashReporter Key: f04e68ec62d3c66057628c9ba9839e30d55937dc
Hardware Model: iPad6,8
Process: TheElements [303]
Path: /private/var/containers/Bundle/Application/888C1FA2-3666-4AE2-9E8E-62E2F787DEC1/TheElements.app/TheElements
Identifier: com.example.apple-samplecode.TheElements
Version: 1.12
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.example.apple-samplecode.TheElements [402]
Date/Time: 2016-08-22 10:43:07.5806 -0700
Launch Time: 2016-08-22 10:43:01.0293 -0700
OS Version: iPhone OS 10.0 (14A5345a)
Report Version: 104
Incident Identifier:crash日誌的標示。
CrashReporter Key:設備標誌符,同一個設備設備的兩份日誌,該標誌相同。
Beta Identifier:崩潰應用程序的設備和供應商組合的唯一標識符。 來自同一供應商和同一設備的兩個應用程序報告將包含相同的值。 此字段僅存在於爲通過TestFlight分發的應用程序生成的崩潰報告中,並替換CrashReporter Key字段。
Process:崩潰進程的可執行文件名。 這與應用程序的信息屬性列表中的CFBundleExecutable鍵的值匹配。
Version:崩潰的進程版本。 此字段的值是崩潰的應用程序的CFBundleVersion和CFBundleVersionString的串聯。
Code Type:崩潰的進程的目標體系結構。 這將是ARM-64,ARM,x86-64或x86之一。
Role:終止時分配給進程的task_role。
OS Version:發生崩潰的操作系統版本,包括內部版本號。
2、Exception Information
下面將列出了Mach異常類型和相關字段,這些字段提供的信息與崩潰性質有關。 但在崩潰報告中並非所有字段都會出現。
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
上面是一個Objective-C異常引起的crash日誌
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]
Triggered by Thread: 0
上面是引用NULL指針引起的crash日誌
Exception Codes:有關異常的處理器特定信息,編碼爲一個或多個64位十六進制數。通常,此字段將不存在,因爲Crash Reporter會解析異常代碼以將其作爲人類可讀的描述呈現在其他字段中。
Exception Subtype:異常代碼的人類可讀名稱。
Exception Message:從異常代碼中提取的其他人類可讀信息。
Exception Note:非特定於一種異常類型的附加信息。如果此字段包含SIMULATED(這不是崩潰),則該進程不會崩潰,但是在系統請求(通常是監視程序)時被殺死。
Termination Reason:終止進程時指定的退出原因信息。進程內部和外部的關鍵系統組件將在遇到致命錯誤(例如,錯誤的代碼簽名,缺少的依賴庫或在沒有適當授權的情況下訪問隱私敏感信息)時終止該進程。 macOS Sierra,iOS 10,watchOS 3和tvOS 10採用了新的基礎設施來記錄這些錯誤,這些操作系統生成的崩潰報告列出了終止原因字段中的錯誤消息。
Triggered by Thread:發生異常的線程。
3、常見的異常
-
Bad Memory Access【EXC_BAD_ACCESS // SIGSEGV // SIGBUS】
當進程去訪問無效的內存或者去寫入只讀存儲器,此時Exception SubType字段包含kern_return_t錯誤描述和訪問的錯誤的內存地址。
- EXC_BAD_ACCESS:訪問了不該訪問的內存,一般該類型後面還會有提示,例如野指針造成的錯誤在Xcode中通常表現爲:Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)
- SIGSEGV:小編沒有遇到過,網上有人說時重複釋放對象造成的、又有人說時試圖訪問未分配給對象的內存造成的~
- SIGBUS:非法地址, 包括內存地址對齊(alignment)出錯。比如訪問一個四個字長的整數, 但其地址不是4的倍數。它與SIGSEGV的區別在於,後者是由於對合法存儲地址的非法訪問觸發的
debug技巧
- 如果在堆棧的上部出現objc_msgSend或者objc_release,則說明該進程在試圖給已釋放的對象發消息,可使用Zombies Instrument幫助調試
- 如果在堆棧的上部出現gpus_ReturnNotPermittedKillClient,則說明進程在後臺渲染OpenGL ES 或Metal。
- 使用Address Sanitizer檢測app,address Sanitizer在編譯咱們的代碼時增加了額外的內存檢測
-
ABnormal Exit【EXC_CRASH // SICABRT】
該進程異常退出。 最常見原因是**未被捕獲的Objective-C / C ++異常以及對abort()**的調用。
如果App Extensions花費太多時間進行初始化(看門狗終止),則會以此異常類型終止。 如果由於啓動時掛起而導致擴展名被終止,則生成的崩潰報告的Exception Subtype將爲LAUNCH_HANG。 因爲擴展沒有main函數,所以花在初始化上的任何時間都發生在擴展和依賴庫中的靜態構造函數和+ load方法中。 你應該儘可能地推遲這項工作。
SIGABRT: 收到Abort信號退出, 通常Foundtion庫中的容器爲了保護狀態正常會做一些檢測, 例如插入nil到數據中等會遇到此類錯誤.
- Trace Trap [EXC_BREAKPOINT // SIGTRAP]
與異常退出類似,此異常是在使用debugger時在其執行的特定點中斷進程。可以使用**__builtin_trap()**函數在代碼中觸發此異常。如果未附加調試器,則終止該過程並生成崩潰報告。
使用較低級別的庫(例如libdispatch)時在遇到致命錯誤時捕獲該進程。有關錯誤的其他信息可以在崩潰報告的“其他診斷信息”部分或設備的控制檯中看到。還有就是Swift代碼運行時出錯以此異常類型終止,例如:具有nil值的非可選類型,強制類型轉換失敗
SIGTRAP 由斷點指令或其它trap指令產生
-
**Illegal Instruction **【EXC_BAD_INSTRUCTION (SIGILL)】
SIGILL 執行了非法指令. 通常是因爲可執行文件本身出現錯誤, 或者試圖執行數據段. 堆棧溢出時也有可能產生這個信號
-
**Quit **【SIGQUIT】
SIGQUIT 進程在因收到SIGQUIT退出時會產生coredump文件, 在這個意義上類似於一個程序錯誤信號。
- Killed 【SIGKILL】
此異常是進程在進行系統請求是產生的,一般是watchOS產生較多
SIGILL 執行了非法指令. 通常是因爲可執行文件本身出現錯誤, 或者試圖執行數據段. 堆棧溢出時也有可能產生這個信號。
等等,以上的說明大部分來自於官網,自己遇到的比較少。
3、堆棧
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 TheElements 0x000000010006bc20 -[AtomicElementViewController myTransitionDidStop:finished:context:] (AtomicElementViewController.m:203)
1 UIKit 0x0000000194cef0f0 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
2 UIKit 0x0000000194ceef30 -[UIViewAnimationState animationDidStop:finished:] + 160
3 QuartzCore 0x0000000192178404 CA::Layer::run_animation_callbacks(void*) + 260
4 libdispatch.dylib 0x000000018dd6d1c0 _dispatch_client_callout + 16
第一行列出了線程號和當前正在執行的調度隊列的標識符。
其餘行列出了有關回溯中各個堆棧幀的詳細信息。 從左到右:
- 第一豎列:堆棧幀號。 堆棧幀以調用順序呈現,其中第0幀是進程暫停時執行的函數。 第1幀是第0幀函數調用的函數,依此類推。
- 第二豎列:堆棧幀的執行函數所在的二進制文件的名稱。
- 第三豎列:對於第0幀,進程停止時執行的機器指令的地址。 對於剩餘的堆棧幀,當控制返回到堆棧幀時將下一次執行的機器指令的地址。
- 第四豎列:在符號化崩潰報告中,堆棧框架中函數的方法名稱。
4、異常
(1)Exception
數組的越界訪問、改變不可改變的對象、沒有實現要求實現的協議等等都會造成異常
注意:給已銷燬的對象發送消息可能不是crash,而是NSInvalidArgumentException,這時可在堆棧中查看是否有
[NSObject(NSObject) doesNotRecognizeSelector:]
,可以在提交自己程序前使用Zombies檢測一下。
(2)Last Exception Backtrace
如果未捕獲到異常,它被一個名爲uncaught exception handler的函數攔截。 對於未捕獲的異常,處理程序將異常消息記錄到設備的控制檯,然後終止該進程。 在Last Exception Backtrace部分下,只將異常回溯寫入生成的崩潰報告,如清單10所示。崩潰報告中省略了異常消息。 如果您收到帶有Last Exception Backtrace的崩潰報告,您應該從原始設備獲取控制檯日誌,以便更好地瞭解導致異常的條件。
相關文檔
如果想查看如何使用Zombies模板工具來修復內存釋放的crash,可以查看Eradicating Zombies with the Zombies Trace Template 。
如果想查看應用歸檔的信息,請參考 App Distribution Guide 。
如果想了解關於crash logs的解讀,請參考Understanding Crash Reports on iPhone OS WWDC 2010 Session 。
如果對異常NSException不瞭解,可以點擊查看NSException的介紹。
https://www.jianshu.com/p/8a46e78a450b
5、例子
工作中突然領導發給的crash日誌,說其他組認爲可能是你之前寫的業務引起的carsh日誌,讓你看看,你能怎麼辦,當然要看了,如下圖
先看到Termination Reason:Namespace ASSERTIOND, Code 0x8badf00d,關於0X8badf00d我們都熟悉是因爲App啓動時間過長或者主線程卡住時間過長,系統被看門狗殺死,但是前面還有Namespace Assertion,於是去stack overflow瀏覽了一番,瞭解了一下crash分析,又看了自己的業務代碼不像是自己引起的啊,其他組的甩鍋技巧很好啊,但是隻有自己的技術強硬,都能招架
先看到Termination Reason:Namespace ASSERTIOND, Code 0x8badf00d,關於0X8badf00d我們都熟悉是因爲App啓動時間過長或者主線程卡住時間過長,系統被看門狗殺死,但是前面還有Namespace Assertion,於是去stack overflow瀏覽了一番,瞭解了一下crash分析,又看了自己的業務代碼不像是自己引起的啊,其他組的甩鍋技巧很好啊,但是隻有自己的技術強硬,都能招架