iOS Crash的捕獲知識
1. crash的型別
crash一般產生自 iOS 的微核心 Mach,然後在 BSD 層轉換成 UNIX SIGABRT 訊號,以標準 POSIX 訊號的形式提供給使用者。NSException 是使用者在處理 App 邏輯時,用程式設計的方法丟擲。
- Mach 異常:EXC_CRASH
- UNIX 訊號:SIGABRT
- NSException 異常:應用層,通過 NSUncaughtExceptionHandler 捕獲
2. crash的捕獲的方式
Mach 異常捕獲。如果想要做mach 異常捕獲,需要註冊一個異常埠,這個異常埠會對當前任務的所有執行緒有效,如果想要針對單個執行緒,可以通過 thread_set_exception_ports註冊自己的異常埠,發生異常時,首先會將異常拋給執行緒的異常埠,然後嘗試拋給任務的異常埠,當我們捕獲異常時,就可以做一些自己的工作,比如,當前堆疊收集等。
-
Unix 訊號捕獲。對於Mach 異常,作業系統會將其轉換為對應的 Unix訊號,所以如果你對Mach不熟悉的話,也可以通過註冊signalHandler的方式來做訊號異常。
signal(SIGABRT, SignalExceptionHandler) signal(SIGSEGV, SignalExceptionHandler) signal(SIGBUS, SignalExceptionHandler) signal(SIGTRAP, SignalExceptionHandler) signal(SIGILL, SignalExceptionHandler)
NSException 捕獲
對於NSException異常,也比較容易處理,通過註冊NSUncaughtExceptionHandler捕獲異常資訊即可,將拿到的NSException細節寫入Crash日誌,上傳到後臺做資料分析
NSSetUncaughtExceptionHandler(UncaughtExceptionHandler)
多個 Crash 收集框架存在時,往往會存在衝突。
不管是對於 Signal 捕獲還是 NSException 捕獲都會存在 handler 覆蓋的問題,正確的做法應該是先判斷是否有前者已經註冊了 handler,如果有則應該把這個 handler 儲存下來,在自己處理完自己的 handler 之後,再把這個 handler 丟擲去,供前面的註冊者處理。
資料: 漫談iOS Crash收集框架
4.堆疊符號解析
堆疊符號化還原有三種常見的方法:
- symbolicatecrash
- mac 下的 atos 工具
- 通過 dSYM 檔案提取地址和符號的對應關係,進行符號還原
// 未符號化前
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崩潰堆疊的符號化解析
輕量級的堆疊採集框架:BSBacktraceLogger
5.啟動連續閃退
-
閃退原因
1. 資料庫損壞:在日常使用如異常退出、斷電,或者錯誤的操作(參考:sqlite corruption causes)。 2. 檔案損壞:處理檔案時如果沒有 @try...catch,損壞檔案會丟擲 NSException 導致 crash 3. 網路返回資料處理異常:比如預期返回陣列,但實際返回了字典,對字典物件執行 -objectAtIndex 方法會產生 crash: unknow selector send to object;,或返回破損的 Tar 包,在解壓失敗導致 crash。 4. 程式碼 bug:當必 crash 的程式碼出現在啟動關鍵路徑中,就會導致連續閃退。 5. 針對 1,可以通過工具修復資料庫,或者刪除 DB。針對2,可以刪除檔案來進行修復。對於 3 和 4,我們需要具體地分析 crash 案例,通過 JSPatch 來進行修復。
-
計時器方法
1. 維護一個計數變數,用於表示連續閃退的次數 2. 在啟動 application:didFinishLaunchingWithOptions: 後使計數加一 3. 接著使用 dispatch_after 方法在 5s 後清零計數,如果 App 活不過 5 秒計數就不會被清零 4. 如果發現計數變數 > n,表明 App 連續 n 次連續閃退,啟動保護流程,重置計數。 5. 當保護流程完成後,進入 App 正常啟動流程
時間陣列比對
在本地儲存一個 App 每次啟動時間、閃退時間、手動關閉時間的時間陣列,然後在 App 啟動時根據分析各個時間戳判斷是否存在連續閃退(當閃退時間減去啟動時間小於閾值 5 秒時,則認為是啟動閃退)
1. App 每次啟動時,記錄當前時間 launchTs,寫入時間陣列;
2. App 每次啟動時,通過 crash 採集庫,獲取上次 crash report 的時間戳 crashTs,寫入時間陣列;
3. App 在接收到 UIApplicationWillTerminateNotification 通知時,記錄當前時間戳 terminateTs,寫入時間陣列。注意,之所以要記錄 terminateTs,是為了排除一種特殊情況,即使用者啟動 App 之後立即手動 kill app。
資料:
iOS 啟動連續閃退保護方案
連續啟動 crash 自修復技術實現與原理解析
兩種 App 啟動連續閃退檢測策略
6.crash收集方式
- 第三方平臺:Fabric、友盟、騰訊 Bugly等,資料會上傳到這些平臺
- 第三方工具: KSCrash、plcrashreporter等,可自行處理收集的crash(傳送到郵箱/上傳自己伺服器)
- 自定義捕獲+堆疊符號化
相關文章
- IOS系統閃退異常(Crash)捕獲處理iOS
- iOS Crash 捕獲及堆疊符號化思路剖析iOS符號
- 捕獲程式Crash,讓你的APP告別閃退APP
- iOS異常捕獲iOS
- Flutter異常捕獲和Crash崩潰日誌收集Flutter
- iOS - block變數捕獲原理iOSBloC變數
- JavaScript事件捕獲冒泡與捕獲JavaScript事件
- iOS 日誌重定向和異常捕獲iOS
- iOS 知識點iOS
- iOS小知識iOS
- 捕獲cookie的值Cookie
- jQuery捕獲jQuery
- iOS容易出錯的知識iOS
- iOS sdk打包知識iOS
- iOS知識梳理:RunLoopiOSOOP
- iOS Crash不崩潰iOS
- 淺談iOS Crash(2)iOS
- 淺談iOS Crash(一)iOS
- JavaScript 事件捕獲JavaScript事件
- 錯誤捕獲
- Audio Hijack教程:如何捕獲iOS裝置中的音訊iOS音訊
- php 正規表示式捕獲組與非捕獲組PHP
- iOS 知識點總結iOS
- iOS知識 – 收藏集 – 掘金iOS
- BIOS知識大全(轉)iOS
- StackOverflowError是無法捕獲的Error
- 事件的捕獲、冒泡、委託事件
- Wireshark的捕獲過濾器過濾器
- iOS-Crash日誌抓取iOS
- iOS中常見Crash總結iOS
- iOS 防止Crash之runtimeiOS
- iOS開發之避免crashiOS
- iOS: Crash檔案解析(一)iOS
- 捕獲 React 異常React
- Swift速成:捕獲列表Swift
- 管理捕獲程式——流
- 【Mysql】捕獲線上sqlMySql
- 【目標區域捕獲-2】目標區域捕獲簡介