[譯]瞭解和分析iOS應用崩潰報告

當一個應用發生崩潰時會產生一份崩潰報告(Crash Report),該報告能夠幫助咱們瞭解崩潰的產生緣由。該文檔講述了關於怎麼樣符號化、理解和分析崩潰報告的相關內容。html

  • 介紹
  • 獲取崩潰和低內存報告
  • 分析崩潰報告
    • 頭部信息
    • 異常代碼
    • 應用具體信息
    • 回溯
    • 線程狀態
    • 二進制映像
  • 瞭解低內存報告
  • 相關文檔
  • 文檔修改記錄

 

介紹

當iOS設備上的應用崩潰時,設備上會爲其生成和保存一份崩潰報告。崩潰報告描述了應用程序在什麼狀況下結束運行的。在大多數狀況下報告會爲每一個執行的線程包含一個完整的回溯(Backtrace),這對於調試應用崩潰問題時很是有用。若是你是iOS開發者,你應該查看這些崩潰報告來了解你的應用存在哪些崩潰,而且應該對這些崩潰進行修復。node

崩潰報告中帶有的回溯必需要先進行符號化(Symbolicated)才能夠進行分析。符號化(Symbolication)指的是使用人可以讀懂的方法名稱和行號來替換回溯裏面的內存地址信息。若是你經過Xcode的Devices窗口得到一臺設備的崩潰日誌,那麼它會在幾秒鐘內自動地將日誌進行符號化。不然你須要手動將.crash文件導入到Xcode的Devices窗口中進行符號化。能夠參考符號化(Symbolication)章節來了解詳細的內容ios

低內存報告與其它崩潰報告不一樣的地方在於它沒有回溯信息。當一個低內存崩潰發生時,你必須檢查你的內存使用圖表(在Debug面板的Memory中查看)而且對低內存警告作出應對處理(如UIViewController中的didReceiveMemoryWarning)。本篇文檔會提供給你一些內存管理方面的參考資料,你應該可以在裏面學習到一些有用的信息。sql

 

獲取崩潰和低內存報告

調試部署iOS應用》一文中講述了怎樣直接從一臺iOS設備中查找崩潰和低內存報告。數據庫

應用分發嚮導-分析崩潰報告》一文中講述了怎麼查看從TestFlight的beta測試用戶和從AppStore下載你的App的用戶那裏所收集到的崩潰日誌信息。編程

 

分析崩潰報告

本章節主要討論一份標準的崩潰報告中出現的每一個小節。bash

 

頭部信息(Header)

每份崩潰報告的開頭都帶有一個頭部信息。網絡

Incident Identifier: E6EBC860-0222-4B82-BF7A-2B1C26BE1E85 

CrashReporter Key: 6196484647b3431a9bc2833c19422539549f3dbe 

Hardware Model: iPhone6,1

Process: TheElements [4637]

Path: /private/var/mobile/Containers/Bundle/Application/5A9E4FC2-D03B-4E19-9A91- 104A0D0C1D44/TheElements.app/TheElements

Identifier: com.example.apple-samplecode.TheElements 

Version: 1.12

Code Type: ARM (Native)

Parent Process: launchd [1]


Date/Time: 2015-04-06 09:14:08.775 -0700 

Launch Time: 2015-04-06 09:14:08.597 -0700

OS Version: iOS 8.1.3 (12B466)

Report Version: 105

清單1.從某份崩潰報告中摘錄下來的頭部信息app

大多數字段的意思都很容易理解,有少數字段須要特殊說明一下:框架

  • Incident Identifier:報告的惟一標識。不一樣的報告該值不相同。

  • CrashReporter Key:每臺設備的匿名標識(並不是真正的設備標識)。若是不一樣的報告出自同一設備,則該值相同。

  • Process:崩潰進程的名稱。該值對應應用信息屬性列表(Info.plist)中的CFBundleExecutable所指定的值。

  • Version:崩潰進程的版本號。該值對應應用信息屬性列表(Info.plist)中的CFBundleVersion和CFBundleVersionString拼接起來的值。

  • Code Type:崩潰進程的目標體系結構。該值是ARM-64或ARM中的一個。

  • OS Version:發生崩潰的操做系統版本號(包括構建版本號)。

 

異常代碼(Exception Codes)

這裏不要和Objective-C/C++的異常混淆了(雖然二者都有多是崩潰的緣由)。本章節列出了Mach的異常類型、子異常類型、處理器專用異常代碼和其它的一些字段來爲崩潰的根本緣由提供更多的信息。最後一個字段列出了觸發崩潰的線程的索引。並非全部字段都會在每份崩潰報告中出現。

Exception Type: EXC_CRASH (SIGABRT)

Exception Codes: 0x0000000000000000, 0x0000000000000000

Triggered by Thread: 0

清單2.從某份崩潰報告中摘錄的異常代碼

下面的章節將對一些公共的異常類型進行說明。

壞的內存訪問 [EXC_BAD_ACCESS // SIGSEGV // SIGBUS]

進程試圖訪問無效的內存地址. 子異常類型字段包含一個kern_return_t的錯誤描述. 子異常代碼(該值跟在子異常類型的後面) 列出被訪問的壞內存地址。

若是objc_msgSend或者objc_release出現接近崩潰線程的回溯頂部, 進程可能試圖向已經釋放的對象發送消息. 你應該經過Instrument工具的Zombies來分析你的應用,以便更好地瞭解觸發該崩潰的條件。

不正常退出[EXC_CRASH // SIGABRT]

進程不正常退出. 致使該異常的大多數狀況是由於沒有捕獲Objective - C/C++所產生的異常。

若是應用擴展(App Extensions)在初始化時花費太多時間將會被結束掉(watchdog結束,watchdog結束指的是watchdog超時後強行終止應用)。若是擴展在啓動時因爲掛起而被殺掉進程,那麼崩潰報告的子異常類型將會是LAUNCH_HANG。由於擴展沒有主函數,所以初始化花費的時間都體如今擴展和依賴庫的靜態構造函數和+load方法中。你應該儘量地避免在靜態構造函數和+load方法中處理過多的工做(也就是文檔中說的延遲大部分的工做處理)。

跟蹤陷阱 [EXC_BREAKPOINT // SIGTRAP]

跟非正常退出類似。該異常是因爲打算給一個附加的調試器在執行特定的斷點來中斷進程時觸發。你能夠在本身的代碼中使用__builtin_trap()方法來觸發此異常。若是沒有被調試器所附加,那麼進程將會結束而且生成一份崩潰報告。

若是Swift代碼在運行時發現一個意外的狀況時,也會以該異常類型結束程序。例如:

  • 爲一個非可選(non-optional)類型被賦值nil
  • 一個有問題的強制類型轉換

經過看崩潰線程的回溯來肯定是在什麼位置出現異常的狀況。

守護資源的侵害 [EXC_GUARD]

進程侵害了一個被守護的資源。系統庫可能會標記守護某些文件描述符,在此以後若是對這些文件描述符做正常的操做將觸發EXC_GUARD異常(當系統想操做這些文件描述符時,會使用特殊的'guarded'私有API)。該異常類型能夠幫助你快速地跟蹤例如關閉一個由系統庫打開的文件描述符這類的問題。舉個例子,若是應用關閉了一個基於SQLite存儲的Core Data的SQLite文件描述符,那麼Core Data隨後也會離奇地崩潰。守護異常越早發現越容易調試。

相關的子異常類型是一個位字段(bitfield),分解以下:

  • [63:61] ‐ 守護類型: 守護資源的類型. 0x2表示一個文件描述符。

  • [60:32] ‐ 特色(Flavor): 違規行爲被觸發的條件。

    • 若是第一位(1 << 0)被設置,則表示進程試圖在被守護的文件描述符上調用close()

    • 若是第二位(1 << 1)被設置,則表示進程試圖在一個被守護的文件描述符上調用dup()、dup2() 、帶有F_DUPFD或者F_DUPFD_CLOEXEC命令的fcntl()方法。

    • 若是第三位(1 << 2)被設置,則表示進程試圖經過套接字(Socket)來發送一個被守護的文件描述符。

    • 若是第五位(1 << 4)被設置,則表示進程試圖對一個被守護的文件描述進行寫操做。

  • [31:0] ‐文件描述符:進程試圖修改的被守護的文件描述符。

資源限制 [EXC_RESOURCE]

進程觸及了消耗資源的限額。這不是一個崩潰,但系統會派發通知告訴進程使用了過多的資源。在子異常類型中會描述確切的資源信息:

  • 子異常類型WAKEUPS表示一個線程每秒中喚醒的次數太多,這迫使CPU喚醒太頻繁而且會損耗電池的壽命。
  • 子異常類型MEMORY表示進程已經越過了系統強制的內存限制。這多是過多佔用內存而致使崩潰的前兆。

其它異常類型

一些崩潰報告可能包含一個未命名的異常類型,是一個十六進制數(如:00000020)。若是你收到這樣的崩潰報告,直接查看下面更多的異常代碼信息:

  • 0xbaaaaaad表示日誌是整個系統的一個堆棧快照(stackshot)而不是一個崩潰報告。經過按下Home鍵和任意音量鍵能夠得到堆棧快照(stackshot)。一般這些日誌是被用戶意外建立的(不當心同時按下了Home鍵+音量鍵),而不是一個錯誤。
  • 0xbad22222表示一個VoIP應用因爲恢復過於頻繁而被iOS結束進程。
  • 0x8badf00d表示一個應用因爲watchdog發生超時而被iOS結束進程。這代表該應用程序在啓動、結束或者響應系統事件時花費太長時間。一個常見的例子是在主線程上實現同步的網絡操做。任何在Thread 0(主線程)上的操做都應該放到後臺線程上執行,或者使用不阻塞主線程的方式進行處理。
  • 0xc00010ff表示一個應用因爲響應一個熱事件(thermal event)而被操做系統殺掉進程。這多是因爲在特定的設備上發生崩潰,或者是操做環境的問題。爲了讓你的程序得到更多有效的提示,請觀看《使用Instruments來提高iOS性能和電量優化的WWDC會議》。
  • 0xdead10cc表示一個應用因爲在後臺運行時還保留着系統的資源(如通信錄數據庫)而被iOS結束進程。

  • 0xdeadfa11表示應用程序被用戶強制退出。當用戶先按住開機鍵直到出現「滑動來關機」界面後再按住Home一段時間後就會出現強制退出的狀況。這可能因爲應用程序沒法響應才使用這種方法來進行強制退出,可是不能保證能夠退出全部應用程序。

注意:從多任務列表中直接結束一個掛起的應用是不會產生崩潰報告的。一旦應用掛起,則iOS能夠在任什麼時候候將其結束,而不產生崩潰報告。

 

 應用具體信息(Application Specific Information)

某些崩潰會寫入一些額外的信息到崩潰報告中。不一樣的結束類型對應該部分的內容也不相同。你能夠經過閱讀本章內容來更好地瞭解一下應用程序結束的情形。

Application Specific Information:

MyApp[134] was suspended with locked system files: 

/private/var/mobile/Library/AddressBook/AddressBook.sqlitedb

清單3.從某份崩潰報告中摘錄的應用具體信息

回溯(Backtrace)

奔潰報告中最有趣的部分就是每一個進程當時已經停止執行的線程回溯。這些回溯的內容就和你使用調試器中止執行應用的時候看到的內容相似。

Thread 0 name: Dispatch queue: com.apple.main-thread 

Thread 0 Crashed:

0 TheElements 0x0000000100063fdc -[AtomicElementViewController myTransitionDidStop:finished:context:] (AtomicElementViewController.m:201)

1 UIKit 0x000000018ca5c2ec -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 184

2 UIKit 0x000000018ca5c1f4 -[UIViewAnimationState animationDidStop:finished:] + 100

3 QuartzCore 0x000000018c380f60 CA::Layer::run_animation_callbacks(void*) + 292

4 libdispatch.dylib 0x0000000198fb9368 _dispatch_client_callout + 12

5 libdispatch.dylib 0x0000000198fbd97c_dispatch_main_queue_callback_4CF + 928

6 CoreFoundation 0x000000018822dfa0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8

7 CoreFoundation 0x000000018822c048 __CFRunLoopRun + 1488

8 CoreFoundation 0x00000001881590a0 CFRunLoopRunSpecific + 392

9 GraphicsServices 0x00000001912fb5a0 GSEventRunModal + 164

10 UIKit 0x000000018ca8aaa0 UIApplicationMain + 1484

11 TheElements 0x000000010005d800 main (main.m:55)

12 libdyld.dylib 0x0000000198fe2a04 start + 0

Thread 1 name: Dispatch queue: com.apple.libdispatch-manager

Thread 1:

0 libsystem_kernel.dylib 0x00000001990e0c94 kevent64 + 8

1 libdispatch.dylib 0x0000000198fc897c_dispatch_mgr_invoke + 272

2 libdispatch.dylib 0x0000000198fbb3b0_dispatch_mgr_thread + 48

...

清單4. 從某份已完成符號化的崩潰報告中摘錄的回溯內容

符號化(Symbolication)

從iOS設備中檢索到的崩潰日誌只有可執行代碼在加載的二進制映像(Binary Images)中的十六進制地址,是沒有包含方法或函數名稱的,而這些方法和函數的名稱被稱爲符號,如清單5所示,你須要將這些地址與符號進行映射。

將回溯的地址解析爲源碼的方法和行號被稱爲符號化 ,這過程須要上傳到AppStore的應用的二進制文件和編譯二進制文件時生成的.dSYM文件。二進制文件和.dSYM文件是一一對應的,不然崩潰報告可能只會顯示部份內容被符號化,如清單6所示。所以,保留每一個分發給用戶的應用包(無論如何分發)和對應的.dSYM文件就很是有必要了。

Thread 0 name: Dispatch queue: com.apple.main-thread

Thread 0 Crashed:

0 TheElements 0x00000001000effdc0x1000e4000+49116

1 UIKit 0x000000018ca5c2ec 0x18ca14000 + 295660

2 UIKit 0x000000018ca5c1f4 0x18ca14000 + 295412

3 QuartzCore 0x000000018c380f600x18c36c000 + 85856

4 libdispatch.dylib 0x0000000198fb93680x198fb8000 + 4968

5 libdispatch.dylib 0x0000000198fbd97c0x198fb8000 + 22908

6 CoreFoundation 0x000000018822dfa0 0x188150000 + 909216

7 CoreFoundation 0x000000018822c048 0x188150000 + 901192

8 CoreFoundation 0x00000001881590a00x188150000 + 37024

9 GraphicsServices 0x00000001912fb5a00x1912f0000 + 46496

10 UIKit 0x000000018ca8aaa0 0x18ca14000 + 486048

11 TheElements 0x00000001000e98000x1000e4000 + 22528

12 libdyld.dylib 0x0000000198fe2a040x198fe0000 + 10756

清單5.從某份未符號化的崩潰報告中摘錄的回溯部分

Thread 0 name: Dispatch queue: com.apple.main-thread

Thread 0 Crashed:

0 TheElements 0x00000001000effdc0x1000e4000 + 49116

1 UIKit 0x000000018ca5c2ec -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 184

2 UIKit 0x000000018ca5c1f4 -[UIViewAnimationState animationDidStop:finished:] + 100

3 QuartzCore 0x000000018c380f60 CA::Layer::run_animation_callbacks(void*) + 292

4 libdispatch.dylib 0x0000000198fb9368_dispatch_client_callout + 12

5 libdispatch.dylib 0x0000000198fbd97c_dispatch_main_queue_callback_4CF + 928

6 CoreFoundation 0x000000018822dfa0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8

7 CoreFoundation 0x000000018822c048__CFRunLoopRun + 1488

8 CoreFoundation 0x00000001881590a0CFRunLoopRunSpecific + 392

9 GraphicsServices 0x00000001912fb5a0GSEventRunModal + 164

10 UIKit 0x000000018ca8aaa0UIApplicationMain + 1484

11 TheElements 0x00000001000e98000x1000e4000 + 22528

12 libdyld.dylib 0x0000000198fe2a04start + 0

清單6.從某份部分符號化崩潰報告中摘錄的回溯部分(系統的棧幀已符號化,但沒有符號化應用程序棧幀)

要點:你必須保留應用程序二進制和它對應的.dSYM文件纔可以完整地進行符號化。你每次提交這些編譯文件到iTunes Connect的時候必需要將它們歸檔。.dSYM文件和應用程序的二進制文件在每次編譯中是對應捆綁的。即便是日後使用的是相同的源文件進行編譯,那產生的.dSYM文件和應用程序的二進制文件也是跟以前的沒有任何關係的。若是你使用Xcode的Build和Archive命令進行編譯,那麼.dSYM 文件和二進制文件將會自動放到一個合適的路徑。否則也能夠是一個經過Spotlight可搜索到的位置(如你的Home目錄)。

使用Xcode的Archive命令能夠很容易地使二進制文件和.dSYM文件配對。當你使用Archive命令(經過選擇Product菜單中的Archive)時,Xcode會一塊兒生成應用的二進制文件和包含符號信息的.dSYM文件並將它們保存到你的Home目錄下。你能夠經過Xcode的Organizer在Archived欄目下找到全部你歸檔過的應用。當符號化崩潰報告時,Xcode會自動從這裏查找對應的歸檔應用;而且能夠經過這裏直接提交歸檔應用到iTunes Connect來確保你release的應用程序二進制文件和.dSYM文件相匹配。

Xcode會自動符號化全部可以匹配程序二進制文件和.dSYM文件的崩潰報告。所以,你須要將全部要符號化的崩潰報告添加到Xcode的Organizer中。其步驟以下:

  1. 將iOS設備鏈接到你的Mac中。
  2. 選擇Xcode的Window菜單中的Devices。
  3. 在左側的DEVICES欄目下選擇鏈接的設備。
  4. 在右側的Device Information欄目下點擊「View Device Logs」按鈕。
  5. 將你的崩潰報告拖拽到彈出面板的左側。
  6. Xcode會自動符號化崩潰報告並顯示符號化後的結果。

異常(Exceptions)

異常在Objective-C中用來講明編程中或者運行時意外發生的錯誤。例如:在集合中的超出範圍訪問、試圖改變一個不可變的對象、沒有實現協議中必須實現的方法或者給對象發送一個不存在的消息等。

注意:給一個已經釋放的對象發送消息會拋出NSInvalidArgumentException異常而不是當即崩潰;當一個新對象分配的內存恰好在已釋放對象的內存地址上時會發生這樣的狀況。若是你的應用崩潰是因爲未捕獲的NSInvalidArgumentException異常(在異常的回溯中看到有-[NSObject(NSObject) doesNotRecognizeSelector:]這樣的信息),能夠考慮使用Instrument的Zombies分析你的應用程序來儘量排出一些不合理的內存管理狀況。

若是一個異常未被捕獲,那麼它會被一個叫未捕獲異常處理器(uncaught exception handler)的方法所攔截。iOS默認的未捕獲異常處理器會將異常信息和回溯打印到設備的控制檯後結束掉程序。只有最後一個未捕獲異常會寫入到崩潰報告的Last Exception Backtrace小節下,如清單7所示。崩潰報告中省略了異常消息。若是你收到一份帶有Last Exception Backtrace小節的崩潰報告,你應該從原來的設備得到控制檯日誌來更好地瞭解致使拋出此次異常的狀況。

Last Exception Backtrace:

(0x18632c2d8 0x197af80e4 0x18632bf5c 0x187165480 0x186257520 0x18b18c7a0 0x18b088384
0x18ad6ca28 0x18ad6c994 0x18af0f25c 0x18ae21ef0 0x18ae21cbc 0x18ae21c3c 0x18ad69760
0x18a6b1e1c 0x18a6ac884 0x18a6ac728 0x18a6abebc 0x18a6abc3c 0x18a6a5364 0x1862e42a4
0x1862e1230 0x1862e1610 0x18620d2d4 0x18fa2b6fc 0x18add2fac 0x1000fd2f4 0x198176a08)

條目7.從某份未符號化的異常報告中摘錄的Last Exception Backtrace小節

帶有Last Exception Backtrace的崩潰日誌僅包含了16進制的地址信息,必須對其進行符號化處理,使它變成可被理解的回溯。如條目8所示:

Last Exception Backtrace:

0   CoreFoundation 0x18632c2d8 __exceptionPreprocess + 132

1   libobjc.A.dylib 0x197af80e4 objc_exception_throw + 60

2   CoreFoundation 0x18632bf5c -[NSException raise] + 12

3   Foundation 0x187165480 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 248

4   CoreFoundation 0x186257520 -[NSArray makeObjectsPerformSelector:] + 248

5   UIKit 0x18b18c7a0 -[UINib instantiateWithOwner:options:] + 1604

6   UIKit 0x18b088384 -[UIViewController _loadViewFromNibNamed:bundle:] + 284

7   UIKit 0x18ad6ca28 -[UIViewController loadViewIfRequired] + 88

8   UIKit 0x18ad6c994 -[UIViewController view] + 32

9   UIKit 0x18af0f25c -[UINavigationController _startCustomTransition:] + 712

10  UIKit 0x18ae21ef0 -[UINavigationController _startDeferredTransitionIfNeeded:] + 468

11  UIKit 0x18ae21cbc -[UINavigationController __viewWillLayoutSubviews] + 56

12  UIKit 0x18ae21c3c -[UILayoutContainerView layoutSubviews] + 200

13  UIKit 0x18ad69760 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 580

14  QuartzCore 0x18a6b1e1c -[CALayer layoutSublayers] + 152

15  QuartzCore 0x18a6ac884 CA::Layer::layout_if_needed(CA::Transaction*) + 320

16  QuartzCore 0x18a6ac728 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32

17  QuartzCore 0x18a6abebc CA::Context::commit_transaction(CA::Transaction*) + 276

18  QuartzCore 0x18a6abc3c CA::Transaction::commit() + 528

19  QuartzCore 0x18a6a5364 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 80

20  CoreFoundation 0x1862e42a4 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32

21  CoreFoundation 0x1862e1230 __CFRunLoopDoObservers + 360

22  CoreFoundation 0x1862e1610 __CFRunLoopRun + 836

23  CoreFoundation 0x18620d2d4 CFRunLoopRunSpecific + 396

24  GraphicsServices 0x18fa2b6fc GSEventRunModal + 168

25  UIKit 0x18add2fac UIApplicationMain + 1488

26  TheElements 0x1000fd2f4 main (main.m:55)

27  libdyld.dylib 0x198176a08 start + 4

清單8.從某份已符號化的崩潰報告中摘錄的Last Exception Backtrace小節.這是一個在應用的故事板中加載一個場景時拋出的異常。由於一個與IBOutlet相關聯的場景元素缺失致使。

注意:若是發現你的應用程序所指定的異常處理域中的異常在拋出時沒有被捕獲,請檢查你的應用或者庫在編譯時是否指定了-no_compact_unwind標識,若是指定了請去掉。

64位的iOS使用了一個「零成本(zero-cost)」的異常實現。在一個「零成本」系統中,每一個可能拋出異常的方法都有描述怎麼unwind堆棧的附加信息。若是一個異常在不具備unwind數據的棧幀中拋出,那麼異常處理將沒法繼續而且進程被中止執行。這有多是一個更上層堆棧異常處理,可是若是有一幀沒有unwind數據那麼將沒有方法知道異常從哪個棧幀拋出。指定-no_compact_unwind標識意味着你的方法沒有unwind table的代碼,因此你不能從這些方法中拋出異常。

此外,若是你的應用程序或庫包含純C代碼,你可能須要指定-funwind-tables標識來讓你的代碼中的全部方法包含unwind table。

線程狀態(Thread State)

該小節列出了崩潰線程的ARM狀態。這是一份在崩潰時寄存器及其值的列表。當你看一份崩潰報告的時候瞭解線程狀態不是必須的,但你能夠利用這些信息來更好的瞭解當時崩潰的狀況。

Thread 0 crashed with ARM Thread State (64-bit):

x0: 0x0000000000000000   x1: 0x0000000000000000   x2: 0x0000000000000000   x3: 0x00000001995f8020

x4: 0x0000000000000000   x5: 0x0000000000000001   x6: 0x0000000000000000   x7: 0x0000000000000000

x8: 0x0000000000000000   x9: 0x0000000000000015  x10: 0x0000000199601df0  x11: 0x0000000b0000000f

x12: 0x00000001741e8700  x13: 0x000001a5995f5779  x14: 0x0000000000000000  x15: 0x0000000044000000

x16: 0x00000001989724d8  x17: 0x0000000188176370  x18: 0x0000000000000000  x19: 0x00000001701dda60

x20: 0x0000000000000001  x21: 0x0000000136606e20  x22: 0x00000001000f6238  x23: 0x0000000000000000

x24: 0x000000019cc640a8  x25: 0x0000000000000020  x26: 0x0000000000000000  x27: 0x0000000000000000

x28: 0x000000019cc577c0  fp: 0x000000016fd1a8d0   lr: 0x00000001000effcc

sp: 0x000000016fd1a860   pc: 0x00000001000effdc cpsr: 0x60000000

清單9.從某份崩潰報告中摘錄的線程狀態小節

二進制映像(Binary Images)

該小節列出了崩潰時加載到進程中的二進制映像。

Binary Images:

0x100058000 - 0x10006bfff TheElements arm64 <77b672e2b9f53b0f95adbc4f68cb80d6>
/var/mobile/Containers/Bundle/Application/CB86658C-F349-4C7A-B73B-CE3B4502D5A4/TheElements.app/TheElements

...

清單10.從某份崩潰報告中摘錄的二進制映像小節中的程序入口

每行列出一個二進制映像的如下細節:

  • 二進制映像在進程中的地址空間。
  • 二進制映像的可執行程序名稱。
  • 二進制映像的體系結構。一個可執行文件能夠包含多個不一樣體系結構的「切片」,但僅有一個「切片」將會加載到進程中。
  • 二進制映像的惟一標識UUID。每一個版本的應用程序/框架和與其對應的符號化.dSYM文件影響此標識的變化。
  • 可執行文件在磁盤上的路徑。

瞭解低內存報告

當發現低內存狀況時,iOS中的虛擬內存系統會依靠協做的應用程序去釋放內存。低內存警告會通知全部運行中的程序和進程來請求釋放內存,但願減小內存的使用量。若是內存壓力得不到釋放,系統可能會終止後臺的進程來緩解內存壓力。若是有足夠的內存被釋放,那麼你的程序能夠繼續運行,不然你的程序會因爲沒有足夠的內存來知足須要而被iOS結束掉,而且會在設備上生成和保存一份低內存報告。

低內存報告的格式和其它的崩潰報告不同,它沒有應用的線程回溯;其開始帶有一個相似於崩潰報告的頭部信息,接下來就是整個系統的內存統計字段的集合。值得關注的是一個叫Page SIze字段的值,其記錄了關於每一個進程在低內存報告中的使用內存分頁數量方面的狀況。

低內存報告中最重要的部分就是進程列表(table of processes)。該表列出了在低內存報告生成時全部正在運行的進程,包括系統的守護進程。若是一個進程被「拋棄(jettisoned)」,其緣由將會記錄在[reason]列中。進程被「拋棄」可能因爲下面的緣由致使:

  • [per‐process‐limit]:該進程跨越了系統施加的內存限制。系統爲全部應用創建的常駐內存進行了限制。跨越該限制的進程將會被終止。

注意:擴展的進程內存限制很低,某些技術,如地圖視圖和SpriteKit都須要較高的內存成本,不適合在擴展中使用。

  • [vm‐pageshortage]/[vm‐thrashing]/[vm]:進程因爲內存壓力而被殺死。
  • [vnode‐limit]:打開了太多的文件。

注意:最前面的應用即便耗盡全部虛擬節點,系統也不會將其殺死。這意味着你的應用在後臺時,即便不是過量使用虛擬節點的源也有可能會被結束。

  • [highwater]: 一個系統守護進程跨越了它的內存使用的最大標記值。

  • [jettisoned]: 其它緣由致使進程被拋棄。

若是你沒有看到緣由中列出你的應用/擴展的進程,那麼可能不是由於內存壓力引發的崩潰。查看.crash文件(上一節講述的)瞭解更多信息。

當你看到一個低內存崩潰時,與其關心那一部分代碼在應用終止時正在執行,倒不如檢查你對內存的使用方式和對低內存警告的響應處理。《在你的應用中查找內存問題》一文中詳細地講述瞭如何使用Instruments的Leaks分析來發現內存泄露,以及如何使用Allocations分析的Mark Heap功能來防止出現被遺棄的內存。《內存使用性能指南》論述了一種正確的方法來應對低內存通知,同時又提供了不少有效使用內存的技巧。同時也建議你看看WWDC2010年會議,使用Instruments進行高級內存分析

重點:Instruments的Leaks和Allocations分析沒法跟蹤全部的內存使用。你須要與Instruments的VM Tracker一塊兒來運行你的應用(包含在Instruments的Allocations的模版中)來查看全部的內存使用量。VM Tracker默認是不開啓的,要想啓動VM Tracker,能夠經過點擊Instruments,選中「Automatic Snapshotting」選項或者手動按下「Snapshot Now」按鈕。

相關文檔

有關如何使用Instruments的Zombies模版來修復內存過分釋放而崩潰的更多信息,請參考《經過Zombies模版來消除殭屍對象

有關應用歸檔的更多信息,請參考《經過Xcode的Archive功能來進應用分發與測試

關於解析崩潰日誌的更多信息,請參考《iPhone OS WWDC 2010會議上的瞭解崩潰報告

文檔修改記錄

日期 備註

2015‐07‐21

Xcode6開展的崩潰報告討論更新

2012‐12‐13

增長更多的異常代碼信息

2012‐03‐28

Xcode4更新,加入關於低內存崩潰報告和更多異常代碼信息。

2011‐03‐01

iOS4或更高版本的變化更新

2010‐07‐06

修復文檔中的Bug

2010‐05‐18

iPhone OS3.2和Xcode 3.2.2的變化更新

2009‐06‐01

添增強調不只須要保存.dSYM文件,還須要保存應用的二進制文件。

2009‐04‐30

iTunes Connect崩潰日誌服務更新

2009‐02‐18

包含一個防止應用程序代碼被符號化的問題解決方案更新

2009‐01‐29

爲開發人員說明如何符號化、瞭解和分析崩潰報告的新文檔

 

翻譯的處女做,若是有不對的地方請狠狠地指出來^_^。

原文連接:https://developer.apple.com/library/ios/technotes/tn2151/_index.html

相關文章
相關標籤/搜索