2、Crash日志組成

Crash我們不得不面對的問題,但是好多人在遇到Crash的時候都無從下手,很多的時候都是憑著感覺找問題。今天我做了5篇文章來幫助我們更加清晰的認(rèn)清iOS中的Crash

想要了解更詳細(xì)的內(nèi)容可以點(diǎn)擊這里

當(dāng)應(yīng)用程序崩潰時,會創(chuàng)建一個崩潰報(bào)告,這對于了解導(dǎo)致崩潰的原因非常有用。本文檔包含有關(guān)如何表示,理解和解釋崩潰報(bào)告的基本信息。

  • 1、介紹
  • 2、獲取崩潰和低內(nèi)存報(bào)告
  • 3、象征性的奔潰報(bào)告
    • 1、位碼(bitCode)
    • 2、確定奔潰報(bào)告是否符號化
    • 3、用Xcode標(biāo)記iOS奔潰報(bào)告
    • 4、用atos表示崩潰報(bào)告
    • 5、符號故障排除
  • 4、崩潰報(bào)告分析
    • 1、頭
    • 2、例外信息
    • 3、其他診斷信息
    • 4、回溯
    • 5、線程狀態(tài)
    • 6、二進(jìn)制圖像
  • 5、了解低內(nèi)存報(bào)告

介紹

當(dāng)應(yīng)用程序崩潰時,會創(chuàng)建崩潰報(bào)告并將其存儲在設(shè)備上。崩潰報(bào)告描述了應(yīng)用程序終止的條件,在大多數(shù)情況下包括每個執(zhí)行線程的完整回溯,并且通常對于調(diào)試應(yīng)用程序中的問題非常有用。您應(yīng)該查看這些崩潰報(bào)告,以了解您的應(yīng)用程序崩潰了什么,然后嘗試修復(fù)它們。

帶有回溯的崩潰報(bào)告需要在進(jìn)行分析之前進(jìn)行符號化。符號化用人類可讀的函數(shù)名稱和行號替換內(nèi)存地址。如果您通過Xcode的設(shè)備窗口從設(shè)備上獲取崩潰日志,那么幾秒鐘后它們將自動被符號化。否則,您需要通過將.crash文件導(dǎo)入Xcode Devices窗口來自行符號化。有關(guān)詳細(xì)信息,請參閱符號崩潰報(bào)告。

一個低內(nèi)存報(bào)告不同之處在于有這類型的報(bào)告沒有回溯其他的崩潰報(bào)告。當(dāng)發(fā)生低內(nèi)存崩潰時,您必須調(diào)查內(nèi)存使用模式以及對低內(nèi)存警告的響應(yīng)。

獲取崩潰和低內(nèi)存報(bào)告

調(diào)試已部署的iOS應(yīng)用程序討論了如何直接從iOS設(shè)備檢索崩潰和低內(nèi)存報(bào)告。

分析“ 應(yīng)用程序分發(fā)指南”中的崩潰報(bào)告討論了如何查看從TestFlight beta測試人員和從App Store下載應(yīng)用程序的用戶收集的聚合崩潰報(bào)告。

象征性的崩潰報(bào)告

符號化是將回溯地址解析為源代碼方法或函數(shù)名稱(稱為符號)的過程。如果沒有首先表示崩潰報(bào)告,則很難確定崩潰發(fā)生的位置。

注意:  低內(nèi)存報(bào)告不需要進(jìn)行符號化。
注意:  macOS的崩潰報(bào)告通常在生成時被符號化或部分符號化。本節(jié)重點(diǎn)介紹iOS,watchOS和tvOS的崩潰報(bào)告,但整個過程與macOS類似。
Crash日志.png

1、當(dāng)編譯器將源代碼轉(zhuǎn)換為機(jī)器代碼時,它還會生成調(diào)試符號,這些符號將編譯后的二進(jìn)制文件中的每個機(jī)器指令映射回源自它的源代碼行。根據(jù)Debug Information Format(DEBUG_INFORMATION_FORMAT)構(gòu)建設(shè)置,這些調(diào)試符號存儲在二進(jìn)制文件或伴隨的Debug Symbol(dSYM)文件中。默認(rèn)情況下,應(yīng)用程序的調(diào)試版本將調(diào)試符號存儲在已編譯的二進(jìn)制文件中,而應(yīng)用程序的發(fā)布版本將調(diào)試符號存儲在配套dSYM文件中以減小二進(jìn)制文件大小。
調(diào)試符號文件和應(yīng)用程序二進(jìn)制文件通過構(gòu)建UUID在每個構(gòu)建的基礎(chǔ)上綁定在一起。為應(yīng)用程序的每個構(gòu)建生成一個新的UUID,并唯一標(biāo)識該構(gòu)建。即使從相同的源代碼重建功能相同的可執(zhí)行文件,使用相同的編譯器設(shè)置,它也將具有不同的構(gòu)建UUID。調(diào)試來自后續(xù)版本的符號文件,即使是來自相同的源文件,也不會與來自其他版本的二進(jìn)制文件互操作。

  • 2、歸檔應(yīng)用程序以進(jìn)行分發(fā)時,Xcode將收集應(yīng)用程序二進(jìn)制文件以及。dSYM將文件存儲并保存在主文件夾內(nèi)的某個位置

  • 3、如果您通過App Store分發(fā)應(yīng)用程序,或使用Test Flight進(jìn)行beta測試,您可以選擇dSYM在將存檔上傳到iTunes Connect時包含該文件。在提交對話框中,選中“為您的應(yīng)用程序包含應(yīng)用程序符號...”。上傳dSYM文件對于接收從TestFlight用戶和選擇共享診斷數(shù)據(jù)的客戶收集的崩潰報(bào)告是必要的

  • 4、當(dāng)您的應(yīng)用程序崩潰時,會創(chuàng)建一個非符號化的崩潰報(bào)告并將其存儲在設(shè)備上。

  • 5、用戶可以按照調(diào)試已部署的iOS應(yīng)用程序中的步驟直接從其設(shè)備檢索崩潰報(bào)告。如果您通過AdHoc或Enterprise分發(fā)分發(fā)了應(yīng)用程序,則這是從用戶獲取崩潰報(bào)告的唯一方法。

  • 6、從設(shè)備檢索到的崩潰報(bào)告是非符號化的,需要使用Xcode進(jìn)行符號化。Xcode使用dSYM與應(yīng)用程序二進(jìn)制文件關(guān)聯(lián)的文件將回溯中的每個地址替換為源代碼中的原始位置。結(jié)果是一個符號化的崩潰報(bào)告。

  • 7、如果用戶選擇與Apple共享診斷數(shù)據(jù),或者用戶已通過TestFlight安裝了應(yīng)用程序的測試版,則崩潰報(bào)告將上載到App Store

  • 8、App Store表示崩潰報(bào)告,并將其與類似的崩潰報(bào)告分組。這種類似崩潰報(bào)告的匯總稱為崩潰點(diǎn)。

  • 9、Xcode的Crashes組織者可以使用符號化的崩潰報(bào)告。

位碼

Bitcode是編譯程序的中間表示。當(dāng)您使用bitcode存檔應(yīng)用程序時,編譯器會生成包含bitcode而不是機(jī)器代碼的二進(jìn)制文件。將二進(jìn)制文件上傳到App Store后,bitcode將編譯為機(jī)器代碼。App Store可能會在將來再次編譯bitcode,以利用未來的編譯器改進(jìn),而無需您采取任何操作

Crash日志1.png

由于二進(jìn)制文件的最終編譯發(fā)生在App Store上,因此Mac不會包含用于表示dSYM從App Review收到的崩潰報(bào)告或從其設(shè)備向您發(fā)送崩潰報(bào)告的用戶所需的調(diào)試符號()文件。雖然dSYM歸檔應(yīng)用程序時會生成一個文件,但它是用于bitcode二進(jìn)制文件,不能用于表示崩潰報(bào)告。App Store使dSYM您可以從Xcode或iTunes Connect網(wǎng)站下載bitcode編譯期間生成的文件。您必須下載這些dSYM文件,以便表示從App Review或從其設(shè)備向您發(fā)送崩潰報(bào)告的用戶收到的崩潰報(bào)告。通過崩潰報(bào)告服務(wù)收到的崩潰報(bào)告將自動進(jìn)行符號化。

App Store編譯的二進(jìn)制文件將具有與最初提交的二進(jìn)制文件不同的UUID。

從Xcode下載dSYM文件

  • 1、在Archives管理器中,選擇最初提交到App Store的存檔
  • 2、單擊“下載dSYMs”按鈕。
    Xcode下載dSYM文件并將其插入選定的存檔。

從iTunes Connect網(wǎng)站下載dSYM文件

  • 1、打開“應(yīng)用詳情”頁面。
  • 2、單擊活動。
  • 3、從“所有構(gòu)建”列表中,選擇一個版本。
  • 4、單擊“ 下載dSYM”鏈接

將“隱藏”符號名稱翻譯回原始名稱

當(dāng)您將帶有bitcode的應(yīng)用程序上傳到App Store時,您可以選擇不通過取消選中“上傳您的應(yīng)用程序的符號以從Apple接收符號化報(bào)告”框來發(fā)送應(yīng)用程序的符號。如果您選擇不將應(yīng)用程序的符號信息發(fā)送給Apple,Xcode將替換您應(yīng)用程序中的符號。dSYM在將應(yīng)用程序發(fā)送到iTunes Connect之前,帶有模糊符號的文件,例如“_hidden#109”。Xcode在原始符號和“隱藏”符號之間創(chuàng)建映射,并將此映射存儲.bcsymbolmap在應(yīng)用程序歸檔內(nèi)的文件中。每個。dSYM文件將有一個相應(yīng)的.bcsymbolmap文件。

在對崩潰報(bào)告進(jìn)行符號化之前,您需要對符號中的符號進(jìn)行去混淆。dSYM從iTunes Connect下載的文件。如果您使用Xcode中的下載dSYMs按鈕,將自動執(zhí)行此去混淆。但是,如果您使用iTunes Connect網(wǎng)站下載。dSYM文件,打開終端并使用以下命令對符號進(jìn)行反模糊處理(用您自己的存檔替換示例路徑和從iTunes Connect下載的dSYMs文件夾):

xcrun dsymutil -symbol-map~ / Library / Developer / Xcode / Archives / 2017-11-23 / MyGreatApp \ 11-23-17 \,\ 12.00 \ PM.xcarchive / BCSymbolMaps~ / Downloads / dSYMs / 3B15C133-88AA-35B0 -B8BA-84AF76826CE0.dSYM

為每個運(yùn)行此命令。dSYM您下載的dSYMs文件夾中的文件。

確定崩潰報(bào)告是否符號化

崩潰報(bào)告可以是非符號化的,完全符號化的或部分符號化的。非符號化的崩潰報(bào)告將不包含回溯中的方法或函數(shù)名稱。相反,您在加載的二進(jìn)制圖像中具有可執(zhí)行代碼的十六進(jìn)制地址。在完全符號化的崩潰報(bào)告中,回溯的每一行中的十六進(jìn)制地址將替換為相應(yīng)的符號。在部分符號化的崩潰報(bào)告中,只有回溯中的某些地址已替換為其相應(yīng)的符號。

顯然,您應(yīng)該嘗試完全符合您收到的任何崩潰報(bào)告,因?yàn)樗鼘⑻峁┯嘘P(guān)崩潰的最深入見解。部分符號化的崩潰報(bào)告可能包含足夠的信息來了解崩潰,具體取決于崩潰的類型以及成功符號化的回溯的哪些部分。非符號化的崩潰報(bào)告很少有用

Crash日志2.png

用Xcode標(biāo)記iOS崩潰報(bào)告

Xcode將自動嘗試表示它遇到的所有崩潰報(bào)告。您需要為符號化做的只是將崩潰報(bào)告添加到Xcode Organizer。

Xcode不接受沒有.crash擴(kuò)展名的崩潰報(bào)告。如果您收到?jīng)]有擴(kuò)展程序或擴(kuò)展程序的崩潰報(bào)告,請?jiān)趫?zhí)行下面列出的步驟之前.txt將其重命名為.crash擴(kuò)展程序。
  • 1、將iOS設(shè)備連接到Mac
  • 2、從“窗口”菜單中選擇“設(shè)備”
  • 3、 在左列的“設(shè)備”部分下,選擇一個設(shè)備
  • 4、單擊右側(cè)面板“設(shè)備信息”部分下的“查看設(shè)備日志”按鈕
  • 5、將崩潰報(bào)告拖到所顯示面板的左列
  • 6、Xcode將自動表示崩潰報(bào)告并顯示結(jié)果

為了表示崩潰報(bào)告,Xcode需要能夠找到以下內(nèi)容

  • 1、崩潰的應(yīng)用程序的二進(jìn)制dSYM文件和文件。
  • 2、dSYM應(yīng)用程序鏈接的所有自定義框架的二進(jìn)制文件和文件。對于使用應(yīng)用程序從源構(gòu)建的框架,它們的dSYM文件將與應(yīng)用程序的dSYM文件一起復(fù)制到存檔中。對于由第三方構(gòu)建的框架,您需要向作者詢問該dSYM文件。
  • 3、崩潰時該應(yīng)用程序運(yùn)行的操作系統(tǒng)的符號。這些符號包含特定操作系統(tǒng)版本(例如iOS 9.3.3)中包含的框架的調(diào)試信息。OS符號是特定于體系結(jié)構(gòu)的 - 用于64位設(shè)備的iOS版本不包含armv7符號。Xcode將自動從連接到Mac的每個設(shè)備復(fù)制OS符號。

如果缺少任何這些,Xcode可能無法表示崩潰報(bào)告,或者可能只是部分地表示崩潰報(bào)告。

用atos表示崩潰報(bào)告

該 ATOS命令將數(shù)字地址轉(zhuǎn)換為其符號等效項(xiàng)。如果有完整的調(diào)試符號信息,則輸出atos將包括文件名和源行號信息。該atos命令可用于在非符號化或部分符號化的崩潰報(bào)告的回溯中表示各個地址。使用atos以下命令表示崩潰報(bào)告的一部分:

  • 1、在回溯中找到要符號化的行。請注意第二列中二進(jìn)制圖像的名稱,以及第三列中的地址。
  • 2、在崩潰報(bào)告底部的二進(jìn)制圖像列表中查找具有該名稱的二進(jìn)制圖像。請注意二進(jìn)制映像的體系結(jié)構(gòu)和加載地址。
Crash日志3.png

符號故障排除

如果Xcode未能完全符合崩潰報(bào)告,可能是因?yàn)槟腗ac缺少dSYM應(yīng)用程序二進(jìn)制dSYM文件的文件,應(yīng)用程序鏈接的一個或多個框架的文件,或者應(yīng)用程序運(yùn)行的OS的設(shè)備符號它墜毀了。以下步驟顯示如何使用Spotlight確定dSYM在Mac上是否存在表示二進(jìn)制圖像中的回溯地址所需的文件。

Crash日志4.png
  • 1、在回溯中找到Xcode無法符號化的行。請注意第二列中二進(jìn)制圖像的名稱
  • 2、在崩潰報(bào)告底部的二進(jìn)制圖像列表中查找具有該名稱的二進(jìn)制圖像。此列表包含崩潰時加載到進(jìn)程中的每個二進(jìn)制映像的UUID。
您可以使用grep命令行工具快速查找二進(jìn)制映像列表中的條目。
$ grep --after-context = 1000“二進(jìn)制圖像:”<崩潰報(bào)告的路徑> | grep <二進(jìn)制名稱>
  • 3、將二進(jìn)制映像的UUID轉(zhuǎn)換為以8-4-4-4-12(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)為一組分隔的32個字符串。請注意,所有字母必須是大寫的。
  • 4、使用mdfind命令行工具使用查詢搜索UUID "com_apple_xcode_dsym_uuids == <UUID>"(包括引號)。
使用mdfind命令行工具搜索dSYM具有給定UUID的文件。
$ mdfind“com_apple_xcode_dsym_uuids == <UUID>”

  • 5、如果Spotlight找到dSYMUUID 的文件,mdfind將打印該dSYM文件的路徑,并可能打印其包含的存檔。如果dSYM找不到UUID 的文件, mdfind將退出而不打印任何內(nèi)容。

分析崩潰報(bào)告

每個崩潰報(bào)告都以標(biāo)題開頭。

Incident Identifier(事件標(biāo)識符): B6FD1E8E-B39F-430B-ADDE-FC3A45ED368C
CrashReporter Key(密鑰): f04e68ec62d3c66057628c9ba9839e30d55937dc
Hardware Model(硬件型號): iPad6,8
Process(進(jìn)程): TheElements [303]
Path(路徑): /private/var/containers/Bundle/Application/888C1FA2-3666-4AE2-9E8E-62E2F787DEC1/TheElements.app/TheElements
Identifier(標(biāo)識符): 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
  • 1、Incident Identifier事件標(biāo)識符:報(bào)告的唯一標(biāo)識符。兩個報(bào)告永遠(yuǎn)不會共享相同的事件標(biāo)識符。
  • 2、CrashReporter KeyCrashReporter密鑰:匿名的每設(shè)備標(biāo)識符。來自同一設(shè)備的兩個報(bào)告將包含相同的值。
  • 3、Beta IdentifierBeta標(biāo)識符:崩潰應(yīng)用程序的設(shè)備和供應(yīng)商組合的唯一標(biāo)識符。來自同一供應(yīng)商和同一設(shè)備的兩個應(yīng)用程序報(bào)告將包含相同的值。此字段僅存在于為通過TestFlight分發(fā)的應(yīng)用程序生成的崩潰報(bào)告中,并替換CrashReporter Key字段。
  • 4、Process進(jìn)程:崩潰進(jìn)程的可執(zhí)行文件名稱。這與CFBundleExecutable應(yīng)用程序的信息屬性列表中的鍵值匹配。
  • 5、Version版本:崩潰的進(jìn)程版本。該字段的值是崩潰的應(yīng)用程序CFBundleVersion和的串聯(lián)CFBundleVersionString。
  • 6、Code Type代碼類型:崩潰的進(jìn)程的目標(biāo)體系結(jié)構(gòu)。這將是一ARM-64,ARM,x86-64,或x86。
  • 7、Role角色:終止時分配給進(jìn)程的task_role。
  • 8、OS Version操作系統(tǒng)版本:發(fā)生崩潰的操作系統(tǒng)版本,包括內(nèi)部版本號。

由于未捕獲的Objective-C異常導(dǎo)致進(jìn)程終止時生成的崩潰報(bào)告中的Exception Codes部分的摘錄。

Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0

當(dāng)進(jìn)程因?yàn)槿∠肗ULL指針而終止時生成的崩潰報(bào)告中的Exception Codes部分的摘錄。

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
  • 1、Exception Codes異常代碼:有關(guān)異常的處理器特定信息,編碼為一個或多個64位十六進(jìn)制數(shù)。通常,此字段將不存在,因?yàn)镃rash Reporter會解析異常代碼以將其作為人類可讀的描述呈現(xiàn)在其他字段中。
  • 2、Exception Subtype異常子類型:異常代碼的人類可讀名稱。
  • 3、Exception Message異常消息:從異常代碼中提取的其他人類可讀信息。
  • 4、Exception Note異常注意:非特定于一種異常類型的附加信息。如果該字段包含,SIMULATED (this is NOT a crash)那么進(jìn)程沒有崩潰,但是在系統(tǒng)請求時被殺死,通常是看門狗
  • 5、Termination Reason終止原因:終止進(jìn)程時指定的退出原因信息。進(jìn)程內(nèi)部和外部的關(guān)鍵系統(tǒng)組件將在遇到致命錯誤時終止進(jìn)程(例如,錯誤的代碼簽名,缺少的依賴庫,或在沒有適當(dāng)權(quán)利的情況下訪問隱私敏感信息)。macOS Sierra,iOS 10,watchOS 3和tvOS 10采用了新的基礎(chǔ)設(shè)施來記錄這些錯誤,這些操作系統(tǒng)生成的崩潰報(bào)告列出了終止原因字段中的錯誤消息
  • 6、Triggered by Thread由線程觸發(fā):發(fā)生異常的線程。

內(nèi)存訪問不良[EXC_BAD_ACCESS // SIGSEGV // SIGBUS]

該進(jìn)程嘗試訪問無效內(nèi)存,或者嘗試以內(nèi)存保護(hù)級別不允許的方式訪問內(nèi)存(例如,寫入只讀內(nèi)存)。該例外子類型字段包含一個kern_return_t描述錯誤,并且被錯誤地訪問的存儲器的地址。

以下是調(diào)試錯誤內(nèi)存訪問崩潰的一些提示:

  • 1、如果崩潰線程的Backtraces頂部objc_msgSend或objc_release附近,則該進(jìn)程可能已嘗試向已釋放的對象發(fā)送消息。您應(yīng)該使用Zombies工具對應(yīng)用程序進(jìn)行概要分析,以便更好地了解此崩潰的情況。
  • 2、如果在崩潰線程gpus_ReturnNotPermittedKillClient的Backtraces頂部附近,則該進(jìn)程被終止,因?yàn)樗诤笈_嘗試使用OpenGL ES或Metal進(jìn)行渲染。請參閱QA1766:如何在移動到后臺時修復(fù)OpenGL ES應(yīng)用程序崩潰。
  • 3、啟用Address Sanitizer運(yùn)行您的應(yīng)用程序。地址清理程序在已編譯的代碼中添加了有關(guān)內(nèi)存訪問的附加檢測。當(dāng)您的應(yīng)用程序運(yùn)行時,如果以可能導(dǎo)致崩潰的方式訪問內(nèi)存,Xcode將提醒您。

異常退出[EXC_CRASH // SIGABRT]

該過程異常退出。使用此異常類型導(dǎo)致崩潰的最常見原因是未被??捕獲的Objective-C / C ++ 異常和調(diào)用abort()。

如果App Extensions花費(fèi)太多時間進(jìn)行初始化(看門狗終止),它將以此異常類型終止。如果由于啟動時掛起而導(dǎo)致擴(kuò)展名被終止,則生成的崩潰報(bào)告的異常子類型將是LAUNCH_HANG。由于擴(kuò)展沒有main函數(shù),因此初始化所花費(fèi)的時間都發(fā)生在+load擴(kuò)展和依賴庫中的靜態(tài)構(gòu)造函數(shù)和方法中。你應(yīng)該盡可能多地推遲這項(xiàng)工作。

跟蹤陷阱[EXC_BREAKPOINT // SIGTRAP]

與異常退出類似,此異常旨在為附加的調(diào)試器提供在其執(zhí)行的特定點(diǎn)中斷進(jìn)程的機(jī)會。您可以使用該__builtin_trap()函數(shù)從您自己的代碼中觸發(fā)此異常。如果未附加調(diào)試器,則終止該過程并生成崩潰報(bào)告。

較低級別的庫(例如libdispatch)會在遇到致命錯誤時捕獲進(jìn)程。有關(guān)錯誤的其他信息可以在崩潰報(bào)告的“ 其他診斷信息”部分或設(shè)備的控制臺中找到。

如果在運(yùn)行時遇到意外情況,則Swift代碼將以此異常類型終止,例如:

  • 1、具有nil值的非可選類型
  • 2、強(qiáng)制類型轉(zhuǎn)換失敗

非法指令[EXC_BAD_INSTRUCTION // SIGILL]
該進(jìn)程試圖執(zhí)行非法或未定義的指令。該進(jìn)程可能試圖通過配置錯誤的函數(shù)指針跳轉(zhuǎn)到無效地址。

在Intel處理器上,ud2操作碼會導(dǎo)致EXC_BAD_INSTRUCTION異常,但通常用于捕獲進(jìn)程以進(jìn)行調(diào)試。如果在運(yùn)行時遇到意外情況,則Intel處理器上的Swift代碼將以此異常類型終止。有關(guān)詳細(xì)信息,請參閱跟蹤陷阱

退出[SIGQUIT]

該進(jìn)程在另一個進(jìn)程的請求下終止,并具有管理其生命周期的權(quán)限。SIGQUIT并不意味著該過程崩潰,但它確實(shí)可能以可檢測的方式行為不端。

在iOS上,如果加載時間過長,主機(jī)應(yīng)用將退出鍵盤擴(kuò)展。崩潰報(bào)告中顯示的Backtraces不太可能指向負(fù)責(zé)的代碼。最有可能的是,擴(kuò)展的啟動路徑上的一些其他代碼需要很長時間才能完成,但在時間限制之前完成,并且當(dāng)擴(kuò)展退出時執(zhí)行移動到Backtraces中顯示的代碼。您應(yīng)該對擴(kuò)展進(jìn)行概要分析,以便更好地了解啟動期間大多數(shù)工作的位置,并將該工作移至后臺線程或?qū)⑵渫七t到以后(擴(kuò)展加載后)。

被殺[SIGKILL]

該過程在系統(tǒng)請求時終止。查看“ 終止原因”字段以更好地了解終止原因。

該終止原因字段將包含一個名稱空間,然后一個代碼。以下代碼特定于watchOS:

  • 1、終止代碼0xc51bad01表示監(jiān)視應(yīng)用程序已終止,因?yàn)樗趫?zhí)行后臺任務(wù)時使用了太多CPU時間。要解決此問題,請優(yōu)化執(zhí)行后臺任務(wù)的代碼以提高CPU效率,或減少應(yīng)用程序在后臺運(yùn)行時執(zhí)行的工作量。
  • 2、終止代碼0xc51bad02表示監(jiān)視應(yīng)用程序因未能在分配的時間內(nèi)完成后臺任務(wù)而終止。要解決此問題,請減少應(yīng)用在后臺運(yùn)行時執(zhí)行的工作量。
  • 3、終止代碼0xc51bad03表示監(jiān)視應(yīng)用程序未能在分配的時間內(nèi)完成后臺任務(wù),并且系統(tǒng)整體上非常繁忙,以至于應(yīng)用程序可能沒有多少CPU時間來執(zhí)行后臺任務(wù)。雖然應(yīng)用程序可以通過減少它在后臺任務(wù)中執(zhí)行的工作量來避免此問題,0xc51bad03但并不表示該應(yīng)用程序執(zhí)行了任何錯誤操作。更有可能的是,由于整體系統(tǒng)負(fù)載,應(yīng)用程序無法完成其工作

保護(hù)資源違規(guī)[EXC_GUARD]

該過程違反了受保護(hù)的資源保護(hù)。系統(tǒng)庫可能會將某些文件描述符標(biāo)記為保護(hù),之后對這些描述符的正常操作將觸發(fā)EXC_GUARD異常(當(dāng)它想要對這些文件描述符進(jìn)行操作時,系統(tǒng)使用特殊的“保護(hù)”私有API)。這有助于您快速跟蹤問題,例如關(guān)閉系統(tǒng)庫打開的文件描述符。例如,如果某個應(yīng)用程序關(guān)閉了用于訪問支持Core Data存儲的SQLite文件的文件描述符,那么Core Data將在以后神秘地崩潰。保護(hù)異常會更快地發(fā)現(xiàn)這些問題,從而使它們更容易調(diào)試。

來自較新版本的iOS的崩潰報(bào)告包括有關(guān)EXC_GUARD在異常子類型和異常消息字段中導(dǎo)致異常的操作的人類可讀詳細(xì)信息。在來自macOS或舊版iOS的崩潰報(bào)告中,此信息被編碼為第一個異常代碼,作為位域,按如下方式分解:

資源限制[EXC_RESOURCE]

該過程超出了資源消耗限制。這是來自操作系統(tǒng)的通知,該進(jìn)程使用了??太多資源。確切的資源列在Exception Subtype字段中。如果包含“ 異常備注”字段NON-FATAL CONDITION,則即使生成了崩潰報(bào)告,也不會終止該進(jìn)程。

  • 1、異常子類型MEMORY表示進(jìn)程已超過系統(tǒng)強(qiáng)加的內(nèi)存限制。這可能是終止超額內(nèi)存使用的先兆。
  • 2、異常子類型WAKEUPS表示進(jìn)程中的線程每秒被喚醒太多次,這迫使CPU經(jīng)常喚醒并消耗電池壽命。

通常,這是由線程到線程的通信(通常使用peformSelector:onThread:或者dispatch_async)引起的,這種通信在不知不覺中發(fā)生的頻率遠(yuǎn)遠(yuǎn)超過它應(yīng)該發(fā)生的頻率。因?yàn)橛|發(fā)此異常的通信類型經(jīng)常發(fā)生,所以通常會有多個具有非常相似的Backtraces的后臺線程- 指示通信的來源。

其他異常類型
某些崩潰報(bào)告可能包含未命名的異常類型,它將打印為十六進(jìn)制值(例如00000020)。如果您收到其中一個崩潰報(bào)告,請直接查看“ 例外代碼”字段以獲取更多信息。

  • 1、異常代碼0xbaaaaaad表示日志是整個系統(tǒng)的堆棧,而不是崩潰報(bào)告。要拍攝疊印,請同時按側(cè)面按鈕和兩個音量按鈕。這些日志通常是由用戶意外創(chuàng)建的,并不表示錯誤。
  • 2、異常代碼0xbad22222表示iOS已終止VoIP應(yīng)用程序,因?yàn)樗^于頻繁地恢復(fù)。
  • 3、異常代碼0x8badf00d表示iOS已終止應(yīng)用程序,因?yàn)榘l(fā)生了監(jiān)視程序超時。應(yīng)用程序啟動,終止或響應(yīng)系統(tǒng)事件花費(fèi)的時間太長。其中一個常見原因是在主線程上進(jìn)行同步網(wǎng)絡(luò)連接。無論什么操作都Thread 0需要移動到后臺線程,或者以不同的方式處理,以便它不會阻塞主線程。
  • 4、異常代碼0xc00010ff表示應(yīng)用程序被操作系統(tǒng)殺死以響應(yīng)熱事件。這可能是由于發(fā)生此崩潰的特定設(shè)備或其運(yùn)行環(huán)境的問題。有關(guān)使您的應(yīng)用程序更高效運(yùn)行的提示,請參閱iOS性能和使用Instruments WWDC會話進(jìn)行功耗優(yōu)化。
  • 5、異常代碼0xdead10cc表示應(yīng)用程序已被操作系統(tǒng)終止,因?yàn)樗趻炱鹌陂g保留了文件鎖或sqlite數(shù)據(jù)庫鎖。如果您的應(yīng)用程序在掛起時對鎖定文件或sqlite數(shù)據(jù)庫執(zhí)行操作,則它必須請求額外的后臺執(zhí)行時間來完成這些操作并在掛起之前放棄鎖定。
  • 6、異常代碼0x2bad45ec表示由于安全違規(guī)而導(dǎo)致應(yīng)用程序被iOS終止。終止描述“在安全模式下檢測到進(jìn)行不安全繪制的過程”表示應(yīng)用程序試圖在不允許的情況下繪制到屏幕,例如屏幕被鎖定時。用戶可能不會注意到此終止,因?yàn)槠聊魂P(guān)閉或發(fā)生此終止時會顯示鎖定屏幕。
使用應(yīng)用切換器終止暫停的應(yīng)用不會生成崩潰報(bào)告。應(yīng)用程序暫停后,它有資格隨時被iOS終止,因此不會生成崩潰報(bào)告。


其他診斷信息
本節(jié)包括特定于終止類型的其他診斷信息,其中可能包括:

  • 1、特定于應(yīng)用程序的信息:在進(jìn)程終止之前捕獲的框架錯誤消息
  • 2、內(nèi)核消息:有關(guān)代碼簽名問題的詳細(xì)信息
  • 3、Dyld錯誤消息:動態(tài)鏈接器發(fā)出的錯誤消息

流程終止時生成的崩潰報(bào)告中的“應(yīng)用程序特定信息”部分的摘錄,因?yàn)檎也坏芥溄拥目蚣?/strong>

Dyld Error Message:
Dyld Message: Library not loaded: @rpath/MyCustomFramework.framework/MyCustomFramework
Referenced from: /private/var/containers/Bundle/Application/CD9DB546-A449-41A4-A08B-87E57EE11354/TheElements.app/TheElements
Reason: no suitable image found.

流程終止時生成的崩潰報(bào)告中的“特定于應(yīng)用程序的信息”部分的摘錄,因?yàn)樗鼰o法快速加載其初始視圖控制器

Application Specific Information:
com.example.apple-samplecode.TheElements failed to scene-create after 19.81s (launch took 0.19s of total time limit 20.00s)

Elapsed total CPU time (seconds): 7.690 (user 7.690, system 0.000), 19% CPU
Elapsed application CPU time (seconds): 0.697, 2% CPU

回溯

崩潰報(bào)告中最有趣的部分是它終止時每個進(jìn)程線程的回溯。這些跟蹤中的每一條都與將進(jìn)程與調(diào)試器暫停時看到的類似

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
5   libdispatch.dylib                 0x000000018dd71d6c _dispatch_main_queue_callback_4CF + 1000
6   CoreFoundation                    0x000000018ee91f2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
7   CoreFoundation                    0x000000018ee8fb18 __CFRunLoopRun + 1660
8   CoreFoundation                    0x000000018edbe048 CFRunLoopRunSpecific + 444
9   GraphicsServices                  0x000000019083f198 GSEventRunModal + 180
10  UIKit                             0x0000000194d21bd0 -[UIApplication _run] + 684
11  UIKit                             0x0000000194d1c908 UIApplicationMain + 208
12  TheElements                       0x00000001000653c0 main (main.m:55)
13  libdyld.dylib                     0x000000018dda05b8 start + 4

Thread 1:
0   libsystem_kernel.dylib            0x000000018deb2a88 __workq_kernreturn + 8
1   libsystem_pthread.dylib           0x000000018df75188 _pthread_wqthread + 968
2   libsystem_pthread.dylib           0x000000018df74db4 start_wqthread + 4

第一行列出了線程號和當(dāng)前正在執(zhí)行的調(diào)度隊(duì)列的標(biāo)識符。其余行列出了有關(guān)回溯中各個堆棧幀的詳細(xì)信息。從左到右:

  • 1、堆棧幀號。堆棧幀以調(diào)用順序呈現(xiàn),其中第0幀是在執(zhí)行暫停時執(zhí)行的函數(shù)。第一幀是在第0幀調(diào)用函數(shù)的函數(shù),依此類推。
  • 2、堆棧幀的執(zhí)行函數(shù)所在的二進(jìn)制文件的名稱。
  • 3、對于第0幀,執(zhí)行停止時執(zhí)行的機(jī)器指令的地址。對于剩余的堆棧幀,當(dāng)控制返回到堆棧幀時將下一次執(zhí)行的機(jī)器指令的地址。
  • 4、在符號化崩潰報(bào)告中,堆??蚣苤泻瘮?shù)的方法名稱。

來自非符號化崩潰報(bào)告的Last Exception Backtrace部分的摘錄。

Last Exception Backtrace:
(0x18eee41c0 0x18d91c55c 0x18eee3e88 0x18f8ea1a0 0x195013fe4 0x1951acf20 0x18ee03dc4 0x1951ab8f4 0x195458128 0x19545fa20 0x19545fc7c 0x19545ff70 0x194de4594 0x194e94e8c 0x194f47d8c 0x194f39b40 0x194ca92ac 0x18ee917dc 0x18ee8f40c 0x18ee8f89c 0x18edbe048 0x19083f198 0x194d21bd0 0x194d1c908 0x1000ad45c 0x18dda05b8)

必須對包含僅包含十六進(jìn)制地址的Last Exception Backtrace的崩潰日志進(jìn)行符號化,以生成可用的回溯

號化崩潰報(bào)告中的Last Exception Backtrace部分的摘錄。在應(yīng)用程序的故事板中加載場景時引發(fā)了此異常。缺少用于連接到場景中元素的相應(yīng)IBOutlet

Last Exception Backtrace:
0   CoreFoundation                    0x18eee41c0 __exceptionPreprocess + 124
1   libobjc.A.dylib                   0x18d91c55c objc_exception_throw + 56
2   CoreFoundation                    0x18eee3e88 -[NSException raise] + 12
3   Foundation                        0x18f8ea1a0 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 272
4   UIKit                             0x195013fe4 -[UIViewController setValue:forKey:] + 104
5   UIKit                             0x1951acf20 -[UIRuntimeOutletConnection connect] + 124
6   CoreFoundation                    0x18ee03dc4 -[NSArray makeObjectsPerformSelector:] + 232
7   UIKit                             0x1951ab8f4 -[UINib instantiateWithOwner:options:] + 1756
8   UIKit                             0x195458128 -[UIStoryboard instantiateViewControllerWithIdentifier:] + 196
9   UIKit                             0x19545fa20 -[UIStoryboardSegueTemplate instantiateOrFindDestinationViewControllerWithSender:] + 92
10  UIKit                             0x19545fc7c -[UIStoryboardSegueTemplate _perform:] + 56
11  UIKit                             0x19545ff70 -[UIStoryboardSegueTemplate perform:] + 160
12  UIKit                             0x194de4594 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1352
13  UIKit                             0x194e94e8c -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 268
14  UIKit                             0x194f47d8c _runAfterCACommitDeferredBlocks + 292
15  UIKit                             0x194f39b40 _cleanUpAfterCAFlushAndRunDeferredBlocks + 560
16  UIKit                             0x194ca92ac _afterCACommitHandler + 168
17  CoreFoundation                    0x18ee917dc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
18  CoreFoundation                    0x18ee8f40c __CFRunLoopDoObservers + 372
19  CoreFoundation                    0x18ee8f89c __CFRunLoopRun + 1024
20  CoreFoundation                    0x18edbe048 CFRunLoopRunSpecific + 444
21  GraphicsServices                  0x19083f198 GSEventRunModal + 180
22  UIKit                             0x194d21bd0 -[UIApplication _run] + 684
23  UIKit                             0x194d1c908 UIApplicationMain + 208
24  TheElements                       0x1000ad45c main (main.m:55)
25  libdyld.dylib                     0x18dda05b8 start + 4

64位iOS使用“零成本”異常實(shí)現(xiàn)。在“零成本”系統(tǒng)中,每個函數(shù)都有附加數(shù)據(jù),這些數(shù)據(jù)描述了如果在函數(shù)中拋出異常,如何展開堆棧。如果在沒有展開數(shù)據(jù)的堆棧幀中拋出異常,則異常處理無法繼續(xù),進(jìn)程將停止。堆棧上可能有一個異常處理程序,但如果沒有一個框架的展開數(shù)據(jù),那么就無法從拋出異常的堆??蚣艿竭_(dá)那里。指定該-no_compact_unwind標(biāo)志意味著您沒有獲得該代碼的展開表,因此您不能在這些函數(shù)之間拋出異常。

此外,如果要在應(yīng)用程序或庫中包含純C代碼,則可能需要指定該-funwind-tables標(biāo)志以包含該代碼中所有函數(shù)的展開表。

線程狀態(tài)

本節(jié)列出了崩潰線程的線程狀態(tài)。這是一個寄存器列表及其執(zhí)行停止時的值。在閱讀崩潰報(bào)告時,無需了解線程狀態(tài),但您可以使用此信息更好地了解崩潰的情況

來自ARM64設(shè)備的崩潰報(bào)告的“線程狀態(tài)”部分的摘錄。

Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x0000000000000000   x1: 0x000000019ff776c8   x2: 0x0000000000000000   x3: 0x000000019ff776c8
x4: 0x0000000000000000   x5: 0x0000000000000001   x6: 0x0000000000000000   x7: 0x00000000000000d0
x8: 0x0000000100023920   x9: 0x0000000000000000  x10: 0x000000019ff7dff0  x11: 0x0000000c0000000f
x12: 0x000000013e63b4d0  x13: 0x000001a19ff75009  x14: 0x0000000000000000  x15: 0x0000000000000000
x16: 0x0000000187b3f1b9  x17: 0x0000000181ed488c  x18: 0x0000000000000000  x19: 0x000000013e544780
x20: 0x000000013fa49560  x21: 0x0000000000000001  x22: 0x000000013fc05f90  x23: 0x000000010001e069
x24: 0x0000000000000000  x25: 0x000000019ff776c8  x26: 0xee009ec07c8c24c7  x27: 0x0000000000000020
x28: 0x0000000000000000  fp: 0x000000016fdf29e0   lr: 0x0000000100017cf8
sp: 0x000000016fdf2980   pc: 0x0000000100017d14 cpsr: 0x60000000

崩潰報(bào)告的二進(jìn)制映像部分中應(yīng)用程序條目的摘錄

Binary Images:
0x100060000 - 0x100073fff TheElements arm64 <2defdbea0c873a52afa458cf14cd169e> /var/containers/Bundle/Application/888C1FA2-3666-4AE2-9E8E-62E2F787DEC1/TheElements.app/TheElements
...

每行包括單個二進(jìn)制圖像的以下詳細(xì)信息:

  • 進(jìn)程中的二進(jìn)制映像的地址空間。
  • 二進(jìn)制文件的二進(jìn)制名稱或包標(biāo)識符(僅限macOS)。在來自macOS的崩潰報(bào)告中,如果二進(jìn)制文件是操作系統(tǒng)的一部分,則前綴為(+)。
  • (僅限macOS)二進(jìn)制文件的短版本字符串和包版本,用短劃線分隔。
  • (僅限iOS)二進(jìn)制圖像的體系結(jié)構(gòu)。二進(jìn)制文件可能包含多個“切片”,每個“切片”支持一個體系結(jié)構(gòu)。這些切片中只有一個加載到過程中。
  • 唯一標(biāo)識二進(jìn)制映像的UUID。此值隨二進(jìn)制的每個構(gòu)建而變化,用于在表示崩潰報(bào)告時定位相應(yīng)的dSYM文件。
  • 磁盤上二進(jìn)制文件的路徑

了解低內(nèi)存報(bào)告

當(dāng)檢測到低內(nèi)存條件時,iOS中的虛擬內(nèi)存系統(tǒng)依賴于應(yīng)用程序的協(xié)作來釋放內(nèi)存。低內(nèi)存通知作為釋放內(nèi)存的請求發(fā)送到所有正在運(yùn)行的應(yīng)用程序和進(jìn)程,希望減少使用的內(nèi)存量。如果內(nèi)存壓力仍然存在,系統(tǒng)可以終止后臺進(jìn)程以減輕內(nèi)存壓力。如果可以釋放足夠的內(nèi)存,您的應(yīng)用程序?qū)⒗^續(xù)運(yùn)行。如果沒有,您的應(yīng)用程序?qū)⒈籭OS終止,因?yàn)闆]有足夠的內(nèi)存來滿足應(yīng)用程序的需求,并且將生成低內(nèi)存報(bào)告并將其存儲在設(shè)備上。

低內(nèi)存報(bào)告的格式與其他崩潰報(bào)告的不同之處在于,應(yīng)用程序線程沒有回溯。低內(nèi)存報(bào)告以類似于崩潰報(bào)告的標(biāo)頭的標(biāo)頭開頭。標(biāo)題后面是列出系統(tǒng)范圍內(nèi)存統(tǒng)計(jì)信息的字段集合。記下“ 頁面大小”字段的值。低內(nèi)存報(bào)告中每個進(jìn)程的內(nèi)存使用量按內(nèi)存頁數(shù)報(bào)告。

低內(nèi)存報(bào)告中最重要的部分是進(jìn)程表。此表列出了生成低內(nèi)存報(bào)告時所有正在運(yùn)行的進(jìn)程,包括系統(tǒng)守護(hù)程序。如果一個過程被“拋棄”,原因?qū)⒘性赱reason]列下。一個過程可能會被拋棄

  • 1、[per-process-limit]:該進(jìn)程超過了系統(tǒng)強(qiáng)加的內(nèi)存限制。駐留內(nèi)存的每進(jìn)程限制由系統(tǒng)為所有應(yīng)用程序建立。越過此限制使該過程有資格終止。
  • 2、[vm-pageshortage] / [vm-thrashing] / [vm]:由于內(nèi)存壓力,該進(jìn)程被終止。
  • 3、[vnode-limit]:打開的文件太多。
  • 4、[highwater]:系統(tǒng)守護(hù)進(jìn)程越過其高水位標(biāo)記以便使用內(nèi)存。
  • 5、[jettisoned]:由于其他原因,該過程被拋棄了。

文章轉(zhuǎn)載自:iOS crash官方文檔

想要更加詳細(xì)的了解,可以參考一下的一些文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容