程序異常捕獲-001-UncaughtException


程序的異常捕獲:

Crash日志記錄的時候是將Crash發生時刻,函數的調用棧,以及線程等信息寫入文件 

01-Crash文件的解析

今天就跟大家一起聊聊 iOS Crash文件的組成以及常用的分析工具。 

一、Crash文件結構 

當程序運行Crash的時候,系統會把運行的最后時刻的運行信息記錄下來,存儲到一個文件中,也就是我們所說的 

Crash文件。iOS的Crash日志通常由以下6各部分組成。 

1、Process Information(進程信息) 

 

Incident Idnetifier-崩潰報告的唯一標識符,不同的CrashCrashReporter Key-設備標識相對應的唯一鍵值(並非真正的設備的UDID,蘋果為了保護用戶隱私iOS6以后已經無法 

獲取)。通常同一個設備上同一版本的App發生Crash時,該值都是一樣的。 

Hardware Model - 代表發生Crash的設備類型,上圖中的“iPad4,4”代表iPad Air 

Process - 代表Crash的進程名稱,通常都是我們的App的名字, []里面是當時進程的ID 

Path - 可執行程序在手機上的存儲位置,注意路徑時到XXX.app/XXX,XXX.app其實是作為一個Bundle的,真正的可 執行文件其實是Bundle里面的XXX,感興趣的可以自己查一下相關資料,有機會我后面也會介紹到 

Identifier-你的App的Indentifier,通常為“com.xxx.yyy”,xxx代表你們公司的域名,yyy代表某一個App 

Version-當前App的版本號,由Info.plist中的兩個字段組成,CFBundleShortVersionString and CFBundleVersion 

Code Type-當前App的CPU架構 

Parent Process-當前進程的父進程,由於iOS中App通常都是單進程的,一般父進程都是launchd 

2、Basic Information 

 

 

Date/Time-Crash發生的時間,可讀的字符串

OS Version-系統版本,()內的數字代表的時Bulid號

Report Version-Crash日志的格式,目前基本上都是104,不同的version里面包含的字段可能有不同 

3、Exception(非常重要) 

 

 

Exception Type-異常類型 

Exception Subtype-異常子類型 

Crashed Thread-發生異常的線程號 

4、Thread Backtrace 

 

 

發生Crash的線程的Crash調用棧,從上到下分別代表調用順序,最上面的一個表示拋出異常的位置,依次往下可以看 到API的調用順序。上圖的信息表明本次Crash出現xxxViewController的323行,出錯的函數調用為 orderCountLoadFailed。 

5、Thread State 

 

 

Crash時發生時刻,線程的狀態,通常我們根據Crash棧即可獲取到相關信息,這部分一般不用關心。 

6、Binary Images 

 

 

Crash時刻App加載的所有的庫,其中第一行是Crash發生時我們App可執行文件的信息,可以看出為armv7,可執行 文件的包得uuid位c0f......cd65,解析Crash的時候dsym文件的uuid必須和這個一樣才能完成Crash的符號化解析。 

二、分析Crash來源

通常來說,crash產生來源於兩種問題:違反iOS系統規則導致的crashApp代碼邏輯 BUG導致的crash,下面分別對他們進行分析。 

違反iOS系統規則產生crash的三種類型: 

1>內存報警閃退 

iOS檢測到內存過低時,它的VM系統會發出低內存警告通知,嘗試回收一些內存;如果情況沒有得到足夠的改善, iOS會終止后台應用以回收更多內存;最后,如果內存還是不足,那么正在運行的應用可能會被終止掉。在Debug模 式下,可以主動將客戶端執行的動作邏輯寫入一個log文件中,這樣程序童鞋可以將內存預警的邏輯寫入該log文件, 當發生如下截圖中的內存報警時,就是提醒當前客戶端性能內存吃緊,可以通過Instruments工具中的Allocations Leaks模塊庫來發現內存分配問題和內存泄漏問題。 

2>響應超時 

當應用程序對一些特定的事件(比如啟動、掛起、恢復、結束)響應不及時,蘋果的Watchdog機制會把應用程序干 掉,並生成一份相應的crash日志。這些事件與下列UIApplicationDelegate方法相對應,當遇到Watchdog日志時,可 以檢查上圖中的幾個方法是否有比較重的阻塞UI的動作。 

application:didFinishLaunchingWithOptions: 2 applicationWillResignActive:3 applicationDidEnterBackground:4 applicationWillEnterForeground: 5 applicationDidBecomeActive: 6 applicationWillTerminate: 

3>用戶強制退出

一看到用戶強制退出,首先可能想到的雙擊Home鍵,然后關閉應用程序。不過這種場景一般是不會產生crash日志 的,因為雙擊Home鍵后,所有的應用程序都處於后台狀態,而iOS隨時都有可能關閉后台進程,當應用阻塞界面並停 止響應時這種場景才會產生crash日志。這里指的用戶強制退出場景,是稍微比較復雜點的操作:先按住電源鍵,直 到出現滑動關機的界面時,再按住Home鍵,這時候當前應用程序會被終止掉,並且產生一份相應事件的crash日 志。 

應用邏輯的Bug 

大多數閃退崩潰日志的產生都是因為應用中的Bug,這種Bug的錯誤種類有很多,比如: 

SEGV:(Segmentation Violation,段違例),無效內存地址,比如空指針,未初始化指針,棧溢出等; SIGABRT:收到Abort信號,可能自身調用abort()或者收到外部發送過來的信號; SIGBUS:總線錯誤。與SIGSEGV不同的是,SIGSEGV訪問的是無效地址(比如虛存映射不到物理內存),而 SIGBUS訪問的是有效地址,但總線訪問異常(比如地址對齊問題); SIGILL:嘗試執行非法的指令,可能不被識別或者沒有權限; 

SIGFPE:Floating Point Error,數學計算相關問題(可能不限於浮點計算),比如除零操作; SIGPIPE:管道另一端沒有進程接手數據; 

常見的崩潰原因基本都是代碼邏輯問題或資源問題,比如數組越界,訪問野指針或者資源不存在,或資源大小寫錯誤

等。

 

三、獲取Crash的途徑

1、本機 

通過xCode連接測試機器,直接在Device中即可讀取到該機器上發生的所有Crash log。 

2、itunes connect通過itunes connect后台獲取到用戶上報的Crash日志。

3、第三方的Crash收集系統 

有很多優秀的第三方Crash收集系統大大的方便了我們收集Crash,甚至還帶了符號化Crash日志的功能。比較常用的 有Crashlytics,Flurry等。 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM