iOS crash 收集與分析

objc_818
texture 異步渲染和佈局引擎 應用啓動 dyld 動態庫 調用 libobjc動態庫 --> _objc_init方法 (map_images(鏡像文件) + load_images(load 方法)) - mainweb

  • load 啓動 - lazy_class(不調用 load 方法 就是 lazy_class)

1、收集方式

一、設備收集

a.使用Xcode從設備獲取崩潰日誌

把你的手機鏈接到Mac,並選擇Xcode->Windows->Device and Simulator,而後點擊View Device Logs,你會看到手機上會有好多Log,其中Type爲Crash的就是崩潰的Log,以下圖:安全

crash1.webp

b.經過設備直接獲取崩潰日誌

1)打開設置->隱私->分析->分析數據,在其中找到你想要的應用程序的日誌,日誌將使用如下格式命名:<應用名稱> _ <崩潰時間> _ <設備名> 2)選擇所需的日誌,複製文本或點擊右上角的分享按鈕分享出去,而且把分享獲得的.ips.synced或者複製文本而來的.txt文件的後綴名改成.crash,由於Xcode不接受沒有.crash擴展名的崩潰日誌。markdown

二、蘋果爸爸發送 crash 報告

16進制數字網絡

dSYM

符號集是咱們每次Archive一個包以後,都會隨之生成的.dSYM文件,這個文件必須使用Xcode進行打包纔有(Debug模式默認是關閉的)。每次發佈一個版本,咱們都須要備份這個文件,以方便之後的調試。
符號集中存儲着文件名、函數名、行號與內存地址的映射表,經過符號集分析崩潰的.Crash文件能夠準確知道具體的崩潰信息。
咱們若是不使用.dSYM文件獲取到的崩潰信息都是不徹底的(官方文檔說了會致使不徹底符號化,也就是一部分符號化好了,一部分沒有)。
每個.dSYM文件都有一個UUID,和.app文件中的UUID對應,表明着是一個應用,而.dSYM文件中每一條崩潰信息也有一個單獨的UUID,用來和程序的UUID進行校對。
複製代碼

2、校驗

在符號化Crash文件以前,你須要準備好.crash和.dSYM並校驗是否匹配app

爲何要校驗:

由於符號集存儲着文件名、函數名、行號的信息,每一次代碼更改後編譯符號集也會隨之變動,因此要想符號化.crash文件,.crash與符號集必須一一對應 也就是說由版本爲1.0的代碼生成了1.0的APP,同時生成了1.0的符號集,1.0的APP發生了Bug,生成了104115的crash文件,也只有1.0的符號集纔可以符號化104115的crash文件,而同時也必須找到1.0的代碼才能根據符號化的crash文件精肯定位到bug產生的地方。 如何判斷.crash、.dSYM與.app(是否匹配你的代碼)是否匹配? 經過UUID來匹配,UUID是Xcode在編譯時自動爲每一個版本生成的惟一標識,即便功能相同的可執行文件是使用相同的編譯器設置從相同的源代碼重建的,它也將具備不一樣的構建UUID,總之UUID是惟一的。 如何經過命令行獲取UUID? 獲取.crash的UUID異步

grep "'Your AppName' arm64" t.crash
複製代碼

獲取.dSYM的UUID函數

dwarfdump --uuid 'Your AppName'.app.dSYM
複製代碼

獲取.app的的UUID工具

dwarfdump --uuid 'Your AppName'.app/'Your AppName'
複製代碼

3、符號化文件

經過dSYM中存儲的信息能夠把crash日誌中的16進制數字一一對應成咱們看得懂的文件名、函數名和行號,這個過程就叫作**符號化**
複製代碼

一、經過XCode自動符號化Crash文件

二、經過命令行工具symbolicatecrash符號化

4、分析

crash 類型oop

一、EXC_BAD_ACCESS

壞內存訪問

野指針引發的崩潰,訪問了一個已經釋放的內存而致使,向已經釋放的對象或向它發送消息時,EXC_BAD_ACCESS就會出現。形成EXC_BAD_ACCESS最多見的緣由是,在初始化方法中初始化變量時用錯了全部權修飾符,這會致使對象過早地被釋放。
複製代碼

引發壞內存的 signal 類型

  • SIGSEGV佈局

    對象已經被釋放,內存不合法,此塊內存地址又沒被覆蓋,因此此內存內垃圾內存,因此調用方法的時候會致使SIGSEGV的錯誤
    複製代碼
  • SIGBUS

    內存地址未對齊
    複製代碼
  • SIGABRT

    致使SIGABRT的錯誤,由於內存中根本就沒有這個空間
    複製代碼

殭屍對象解決

是一個環境變量,用來調試與內存相關的問題,跟蹤對象的釋放過程。啓用了NSZombieEnabled的話,它會用一個殭屍實現來去你的默認的dealloc實現,也就是在引用計數降到0時,該殭屍實現會將該對象轉換成殭屍對象。殭屍對象的做用是在你向它發送消息時,它會顯示一段日誌並自動跳入調試器
複製代碼

二、EXC_ARITHETIC

除 0 操做

三、SIGILL

SIGILL表明signal illegal instruction(非法指令信號)。當在處理器上執行非法指令時,它就會發生。執行非法指令是指,將函數指針會給另一個函數時,該函數指針因爲某種緣由是壞的,指向了一段已經釋放的內存或是一個數據段。有時你收到的是EXC_BAD_INSTRUCTION而不是SIGILL,雖然它們是一回事,不過EXC_*等同於此信號不依賴體系結構。
複製代碼

四、SIGABRT

SIGABRT表明SIGNAL ABORT(停止信號)。當操做系統發現不安全的狀況時,它可以對這種狀況進行更多的控制;必要的話,它能要求進程進行清理工做。在調試形成此信號的底層錯誤時,並無什麼妙招

通常表示內存根本沒這個空間
複製代碼

五、SIGBUS

內存未對齊
複製代碼

五、watchdog 超時

在iOS上,它常常出如今執行一個同步網絡調用而阻塞主線程的狀況。所以,永遠不要進行同步網絡調用。
複製代碼

5、Mach異常和Signal信號

blog.csdn.net/u013602835/…

若是想要監聽異常其實就是去監聽Mach異常和Signal信號。其實系統已經給咱們提供了一個方法去監聽程序產生的異常,經過NSSetUncaughtExceptionHandler(入參是一個C函數)方法就能夠直接捕獲異常信息。可是這個方法捕獲的異常有限,不能捕獲因爲內存訪問錯誤等產生的signal,因此若是想要監聽絕大多數的異常須要咱們本身經過註冊signal(signal的類型,回調方法)來捕獲信號進行監聽。

void InstallUncaughtExceptionHandler(void) {
    NSSetUncaughtExceptionHandler(&HandleException); //系統的方法
    //添加想要監聽的signal類型,當發出相應類型的signal時,會回調SignalHandler方法
    signal(SIGABRT, SignalHandler);
    signal(SIGILL, SignalHandler);
    signal(SIGSEGV, SignalHandler);
    signal(SIGFPE, SignalHandler);
    signal(SIGBUS, SignalHandler);
    signal(SIGPIPE, SignalHandler);
複製代碼
相關文章
相關標籤/搜索