收集crash日志方式
1.設備上直接查看
路徑:設置 -> 隱私 -> 分析 -> 分析數據
2.xcode獲取設備上信息
路徑:xcode菜單欄Window -> Devices and Simulators -> 選中設備 -> View Device Logs
3.xcode獲取發布版本崩潰信息
路徑:xcode菜單欄Window -> Organizer -> 選擇項目 -> Tab選擇Crashes
下圖中:
1為崩潰信息列表;
2可選擇發布版本;
3為具體崩潰堆棧信息;
4可選擇源代碼,跟蹤具體崩潰位置。
4.代碼捕捉崩潰信息
1.第三方平臺:bugly、友盟;
2.代碼捕獲crash,監聽NSSetUncaughtExceptionHandler和signal事件,可借助第三方工具KSCrash、plcrashreporter等。
~
~
~
~
~
~
代碼捕獲crash
Demo地址: https://github.com/PiPiXie/Demo.git
crash的類型
crash一般產生自 iOS 的微內核 Mach,然后在 BSD 層轉換成 UNIX SIGABRT 信號,以標準 POSIX 信號的形式提供給用戶。NSException 是使用者在處理 App 邏輯時,用編程的方法拋出
crash的捕獲的方式
Mach 異常捕獲。基于Mach內核編程,需要對內核有一定了解.
Unix 信號捕獲。對于Mach 異常,操作系統會將其轉換為對應的 Unix信號,可以通過注冊signalHandler的方式來做信號異常。
signal(SIGABRT, SignalExceptionHandler)
~
NSException 捕獲。應用層,通過 NSUncaughtExceptionHandler 捕獲,因為堆棧中不會有出錯代碼,所以需要獲取NSException對象中的reason,name,callStackSymbols。然后把細節寫入Crash日志,上傳到后臺做數據分析.
NSSetUncaughtExceptionHandler(UncaughtExceptionHandler)
~
debug模式下,signal監聽無效問題
在debug模式下,如果你觸發了signal崩潰,那么應用會直接崩潰到主函數,斷點都沒用,此時沒有任何log信息顯示出來,如果你想看log信息的話,你需要在會crash的那行代碼上打斷點,然后在console中輸入pro hand -p true -s false SIGABRT命令(SIGABRT只是示例,應輸對應的信號錯誤),然后下一步,不然你啥也看不到。
~
沖突
當項目中存在多個crash收集框架時往往會存在沖突。
因為不管是對于 Signal 捕獲還是 NSException 捕獲都會存在 handler 覆蓋的問題,應該先判斷handler是否存在,如果存在剛 保存handler,處理完自己的 handler 后,再把這個 handler 拋出去,供前面的注冊者處理,詳情見demo。
~
堆棧收集
無論Unix 信號捕獲,還是NSException 捕獲,都只能獲取到當前線程的堆棧,如果想獲取所有線程的堆棧,可以考慮用這個框架:BSBacktraceLogger
~
堆棧符號解析
無論是采用何種方式收集到的崩潰信息,都會面臨同一個問題,堆棧大概率是沒有被符號化過的,對于開發者來說,是根本看不懂的,那就無從談起問題的定位了。這個時候就需要進行堆棧符號化了。
堆棧符號化還原有三種常見的方法:
1.symbolicatecrash
2.mac 下的 atos 工具
3.通過 dSYM 文件提取地址和符號的對應關系,進行符號還原
獲取dSYM文件:xcode菜單欄Window -> Organizer -> 選擇項目 -> Tab選擇Crashes -> achieve包 -> show in finder -> 右鍵顯示包內容 -> 打開dSYMs文件夾
// 未符號化前
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x000000018b816f30 0x18b7fc000 + 110384 (objc_msgSend + 16)
1 UIKit 0x0000000192e0a79c 0x192c05000 + 2119580 (<redacted> + 72)
2 UIKit 0x0000000192c4db48 0x192c05000 + 297800 (<redacted> + 312)
3 UIKit 0x0000000192c4d988 0x192c05000 + 297352 (<redacted> + 160)
4 QuartzCore 0x00000001900d6404 0x18ffc5000 + 1119236 (<redacted> + 260)
// 符號化后
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x000000018b816f30 objc_msgSend + 16
1 UIKit 0x0000000192e0a79c -[UISearchDisplayController _sendDelegateDidBeginDidEndSearch] + 72
2 UIKit 0x0000000192c4db48 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
3 UIKit 0x0000000192c4d988 -[UIViewAnimationState animationDidStop:finished:] + 160
4 QuartzCore 0x00000001900d6404 CA::Layer::run_animation_callbacks(void*) + 260
注:Xcode的Organizer內置了symbolicatecrash,所以我們才可以直接看到符號化的崩潰堆棧日志。
資料:實戰iOS崩潰堆棧的符號化解析
~
~
~
~
Crash防護
Crash類型
1.unrecognized selector crash
2.KVO crash
3.NSNotification crash
4.NSTimer crash
5.Container crash(數組越界,插nil等)
6.NSString crash (字符串操作的crash)
7.UI not on Main Thread Crash (非主線程刷UI(機制待改善))
防護
資料:大白健康系統