崩潰日志詳解上

出處:http://www.iteye.com轉自? http://www.raywenderlich.com/zh-hans/30818/ios應用崩潰日志揭秘?

?本文作者是? Soheil Moayedi Azarpour, 他是一名獨立iOS開發者。作為一名應用開發者,你是否有過如下經歷?Learn how to make sense of crash logs! 為確保你的應用正確無誤,在將其提交到應用商店之前,你必定進行了大量的測試工作。它在你的設備上也運行得很好,但是,上了應用商店后,還是有用戶抱怨會閃退 ! 如果你跟我一樣是個完美主義者,你肯定想將應用做到盡善盡美。于是你打開代碼準備修復閃退的問題……但是,從何處著手呢? 這時iOS崩潰日志派上用場了。在大多數情況下,你能從中了解到關于閃退的詳盡、有用的信息。 通過本教程,你將學習到一些常見的崩潰日志案例,以及如何從開發設備和iTunes Connect上獲取崩潰日志文件。你還將學習到符號化( symbolication),從日志追蹤到代碼 。你還將學習調試一個在待定情況下會閃退的應用。 讓我們開始動手吧!什么是崩潰日志,從哪里能得它?iOS設備上的應用閃退時,操作系統會生成一個崩潰報告,也叫崩潰日志,保存在設備上。 崩潰日志上有很多有用的信息,包括應用是什么情況下閃退的。通常,上面有每個正在執行線程的完整堆棧跟蹤信息,所以你能從中了解到閃退發生時各線程都在做什么,并分辨出閃退發生在哪個線程上。 有幾種方法可以從設備上獲取崩潰日志。 設備與電腦上的iTunes Store同步后,會將崩潰日志保存在電腦上。根據電腦操作系統的不同,崩潰日志將保存在以下位置: Mac OS X: ~/Library/Logs/CrashReporter/MobileDevice/ Windows XP:? C:Documents and SettingsApplication DataApple ComputerLogsCrashReporterMobileDeviceWindows Vista or 7:C:UsersAppDataRoamingApple ComputerLogsCrashReporterMobileDevice當用戶抱怨閃退時,你可以要求他讓設備與iTunes同步,并根據操作系統的不同,到上述位置把崩潰日志下載下來,然后通過電子郵件發送給你。

你必需盡量獲取用戶設備生成的所有崩潰日志。因為崩潰日志越多,就越容易診斷問題所在!

另外,如果你裝了Xcode,也能很容易通過Xcode從你的設備上獲得崩潰日志。將iOS設備連接到電腦上,然后打開Xcode。從菜單欄上選擇? Window? 菜單, 然后選擇? Organizer (快捷方式是 Shift-CMD-2).

在 Organizer 窗口上, 選中? Devices 標簽欄. 在左側的導航面板上,選中? Device Logs, 如下圖所示:

Devices tab in Xcode Organizer

看看上圖,左側有好幾個 Device Logs 菜單項.? LIBRARY 下面的Device Logs是你所有設備(曾經連接到Xcode的)的日志 。每個設備下面的 Device Logs 是對應設備的日志。

應用提交到App Store后,你也能從? iTunes Connect 獲取到用戶的崩潰日志. 登錄到 iTunes Connect 上, 選擇 Manage Your Applications, 點擊相應的應用, 點擊應用圖標下面的? View Details 按鈕, 然后點擊右欄Links部分的? Crash Reports 。

Crash Reports in iTunes Connect

如果沒有崩潰日志,試試點擊 Refresh 按鈕刷新一下。如果你的應用還賣得不多,或者剛上架不久,iTunes Connect賬號上也可能還沒有任何崩潰日志。

如果iTunes Connect上有崩潰日志,你將看到如下圖:

Crash Reports in iTunes Connect

有時,盡管有用戶報告閃退,你仍然看不到崩潰報告。這時,最好讓用戶直接把崩潰報告發送給你。

什么情況下會產生崩潰日志?

兩種主要情況會產生崩潰日志:

應用違反操作系統規則。

應用中有Bug。

違反iOS規則包括在啟動、恢復、掛起、退出時watchdog超時、用戶強制退出和低內存終止。讓我們詳細了解一下吧。

Watchdog 超時機制

從iOS 4.x開始,退出應用時,應用不會立即終止,而是退到后臺。

但是,如果你的應用響應不夠快,操作系統有可能會終止你的應用,并產生一個崩潰日志。這些事件與下列UIApplicationDelegate方法相對應:

application:didFinishLaunchingWithOptions:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationDidBecomeActive:

applicationWillTerminate:

上面所有這些方法,應用只有有限的時間去完成處理。如果花費時間太長,操作系統將終止應用。

注意: 如果你沒有把需要花費時間比較長的操作(如網絡訪問)放在后臺線程上就很容易發生這種情況。關于如果避免這種情況的信息,請參考我們的另外兩篇教程:? Grand Central Dispatch 和? NSOperations。

用戶強制退出

iOS 4.x開始支持多任務。如果應用阻塞界面并停止響應, 用戶可以通過在主屏幕上雙擊Home按鈕來終止應用。此時,操作應用將生成一個崩潰日志。

注意: 雙擊Home按鈕后,你將看到運行過的所有應用。那些應用不一定是正在運行,也不一定是被掛起。

通常,用戶點擊Home按鈕時,應用將在后臺保留約10分鐘,然后操作系統自動將其終止。 所以雙擊Home按鈕顯示的應用列表只是表明那是一系列過去打開過的應用。刪除那些應用的圖標不會產生任何崩潰日志。

低內存終止

子類化UIViewController時,你或許已經注意到 didReceiveMemoryWarning方法。

在前臺運行的應用擁有訪問和使用內存的最高優化級。然而,這并不意味著該應用能使用設備的所有可用內存 ——每個應用只能使用一部分可用內存。

當內存使用達到一定程度時,操作系統將發出一個? UIApplicationDidReceiveMemoryWarningNotification 通知。同時,調用? didReceiveMemoryWarning 方法。

此時,為了讓應用繼續正常運行,操作系統開始終止在后臺的其他應用以釋放一些內存。所有后臺應用被終止后,如果你的應用還需要更多內存,操作系統會將你的應用也終止掉,并產生一個崩潰日志。而在這種情況下被終止的后臺應用,不會產生崩潰日志。

注意: 根據? 蘋果文檔, Xcode不會自動添加低內存日志。你必需手動獲取日志。 然而,根據我的個人經驗,使用 Xcode 4.5.2, 低內存日志也會自動導入,只是”Process”和”Type”屬性都被標為Unknown(未知)。

另外,值得一提的是在極短時間內分配一大塊內存將給系統內存帶來巨大負擔。這樣,也會產生內存警告的通知。

應用中有Bug

如你所想,大多數閃退都是由于應用中有Bug,因此大多數崩潰日志的產生都是因為應用中的Bug。Bug的種類的有很多。

在本教程的后半部分,你將通過調試一個會產生崩潰日志的含有Bug的應用,學習如何找到問題所在并進行修復!

崩潰日志的實例

讓我們看看一個崩潰日志的實例,以使你在處理一些實際問題之前心里有譜。

事不宜遲,見見你的新朋友吧:

[objc]? view plain copy

// 1: 進程信息

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:? 5a56599d836c4f867f6eec76afee451bf9ae5f31

Hardware Model:? ? ? iPhone4,1

Process:? ? ? ? Rage Masters [4155]

Path:? ? ? ? ? ? /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

Identifier:? ? ? Rage Masters

Version:? ? ? ? ??? (???)

Code Type:? ? ? ARM (Native)

Parent Process:? launchd [1]

// 2: 基本信息

Date/Time:? ? ? 2012-10-17 21:39:06.967 -0400

OS Version:? ? ? iOS 6.0 (10A403)

Report Version:? 104

// 3: 異常

Exception Type:? 00000020

Exception Codes: 0x000000008badf00d

Highlighted Thread:? 0

// 4: 線程回溯

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

Thread 0:

0? libsystem_kernel.dylib? ? ? ? ? ? 0x327f2eb4 mach_msg_trap + 20

1? libsystem_kernel.dylib? ? ? ? ? ? 0x327f3048 mach_msg + 36

2? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36bd4040 __CFRunLoopServiceMachPort + 124

3? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36bd2d9e __CFRunLoopRun + 878

4? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36b45eb8 CFRunLoopRunSpecific + 352

5? CoreFoundation? ? ? ? ? ? ? ? ? ? 0x36b45d44 CFRunLoopRunInMode + 100

6? CFNetwork? ? ? ? ? ? ? ? ? ? ? ? 0x32ac343e CFURLConnectionSendSynchronousRequest + 330

7? Foundation? ? ? ? ? ? ? ? ? ? ? ? 0x346e69ba +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 242

8? Rage Masters? ? ? ? ? ? ? ? ? ? ? 0x000d4046 0xd2000 + 8262

Thread 1:

0? libsystem_kernel.dylib? ? ? ? ? ? 0x32803d98 __workq_kernreturn + 8

1? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a987cf6 _pthread_workq_return + 14

2? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a987a12 _pthread_wqthread + 362

3? libsystem_c.dylib? ? ? ? ? ? ? ? 0x3a9878a0 start_wqthread + 4

// 5: 線程狀態

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

r0: 0x00000000? ? r1: 0x00000000? ? ? r2: 0x00000001? ? ? r3: 0x39529fc8

r4: 0xffffffff? ? r5: 0x2fd7d301? ? ? r6: 0x2fd7d300? ? ? r7: 0x2fd7d9d0

r8: 0x2fd7d330? ? r9: 0x3adbf8a8? ? r10: 0x2fd7d308? ? r11: 0x00000032

ip: 0x00000025? ? sp: 0x2fd7d2ec? ? ? lr: 0x001bdb25? ? ? pc: 0x30301838

cpsr: 0x00000010

// 6: 二進制映像

Binary Images:

0xd2000 -? ? 0xd7fff +Rage Masters armv7? /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

0x2fe41000 - 0x2fe61fff? dyld armv7? /usr/lib/dyld

0x327f2000 - 0x32808fff? libsystem_kernel.dylib armv7? /usr/lib/system/libsystem_kernel.dylib

0x328a8000 - 0x328bdfff? libresolv.9.dylib armv7? /usr/lib/libresolv.9.dylib

0x32a70000 - 0x32b35fff? CFNetwork armv7? /System/Library/Frameworks/CFNetwork.framework/CFNetwork

0x32b7a000 - 0x32cc3fff? libicucore.A.dylib armv7? /usr/lib/libicucore.A.dylib

0x32cc4000 - 0x32cc5fff? CoreSurface armv7? /System/Library/PrivateFrameworks/CoreSurface.framework/CoreSurface

0x32f65000 - 0x32f8afff? OpenCL armv7? /System/Library/PrivateFrameworks/OpenCL.framework/OpenCL

這報告看起來像天書。:) 我們分幾部分來解讀吧:

(1) 進程信息

第一部分是閃退進程的相關信息。

Incident Identifier是崩潰報告的唯一標識符。

CrashReporter Key 是與設備標識相對應的唯一鍵值。雖然它不是真正的設備標識符,但也是一個非常有用的情報:如果你看到100個崩潰日志的CrashReporter Key值都是相同的,或者只有少數幾個不同的CrashReport值,說明這不是一個普遍的問題,只發生在一個或少數幾個設備上。

Hardware Model 標識設備類型。 如果很多崩潰日志都是來自相同的設備類型,說明應用只在某特定類型的設備上有問題。上面的日志里,崩潰日志產生的設備是iPhone 4s。

Process 是應用名稱。中括號里面的數字是閃退時應用的進程ID。

接下來幾行不言自明,無需贅述。

(2) 基本信息

這部分給出了一些基本信息,包括閃退發生的日期和時間,設備的iOS版本。如果有很多崩潰日志都來自iOS 6.0,說明問題只發生在iOS 6.0上。

(3) 異常

在這部分,你可以看到閃退發生時拋出的異常類型。還能看到異常編碼和拋出異常的線程。根據崩潰報告類型的不同,在這部分你還能看到一些另外的信息。

(4) 線程回溯

這部分提供應用中所有線程的回溯日志。 回溯是閃退發生時所有活動幀清單。它包含閃退發生時調用函數的清單。看下面這行日志:

2? ? XYZLib? ? 0x34648e88? ? 0x83000 + 8740

它包括四列:

幀編號—— 此處是2。

二進制庫的名稱 ——此處是 XYZLib.

調用方法的地址 ——此處是 0x34648e88.

第四列分為兩個子列,一個基本地址和一個偏移量。此處是0×83000 + 8740, 第一個數字指向文件,第二個數字指向文件中的代碼行。

(5) 線程狀態

這部分是閃退時寄存器中的值。一般不需要這部分的信息,因為回溯部分的信息已經足夠讓你找出問題所在。

(6) 二進制映像

這部分列出了閃退時已經加載的二進制文件。

符號化Symbolication

第一次看到崩潰日志上的回溯時,你或許會覺得它沒什么意義。我們習慣使用方法名和行數,而非像這樣的神秘位置:

6? ? Rage Masters? ? 0x0001625c? ? 0x2a000 + 3003

將這些十六進制地址轉化成方法名稱和行數的過程稱之為符號化。

從Xcode的Organizer窗口獲取崩潰日志后過幾秒鐘,崩潰日志將被自動符號化。上面那行被符號化后的版本如下 :

6? ? Rage Masters? ? 0x0001625c? ? -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)

Xcode符號化崩潰日志時,需要訪問與App Store上對應的應用二進制文件以及生成二進制文件時產生的? .dSYM 文件。必需完全匹配才行。否則,日志將無法被完全符號化。

所以,保留每個分發給用戶的編譯版本非常重要。提交應用前進行歸檔時,Xcode將保存應用的二進制文件。可以在Xcode Organizer的Archives標簽欄下找到所有已歸檔的應用文件。

在發現崩潰日志時,如果有相匹配的.dSYM文件和應用二進制文件,Xcode會自動對崩潰日志進行符號化。如果你換到別的電腦或創建新的賬戶,務必將所有二進制文件移動到正確的位置,使Xcode能找到它們。

注意: 你必需同時保留應用二進制文件和.dSYM文件才能將崩潰日志完整符號化。每次提交到iTunes Connect的構建都必需歸檔。

.dSYM文件和二進制文件是特定綁定于每一次構建和后續構建的,即使來自相同的源代碼文件,每一次構建也與其他構建不同,不能相互替換。

如果你使用Build 和 Archive 命令,這些文件會自動放在適當位置。 如果不是使用Build 和 Archive命令,放在Spotlight能夠搜索到的位置(比如Home目錄)即可。

低內存閃退

因為低內存崩潰日志與普通崩潰日志略有不同,所以本教程特別分開說明一下。:]

iOS設備檢測到低內存時,虛擬內存系統發出通知請求應用釋放內存。這些通知發送到所有正在運行的應用和進程,試圖收回一些內存。

如果內存使用依然居高不下,系統將會終止后臺線程以緩解內存壓力。如果可用內存足夠,應用將能夠繼續運行而不會產生崩潰報告。否則,應用將被iOS終止,并產生低內存崩潰報告。

低內存崩潰日志上沒有應用線程的堆棧回溯。相反,上面顯示的是以內存頁數為單位的各進程內存使用量。(在撰寫本文的時候,一個內存頁的大小是4KB。)

被iOS因釋放內存頁終止的進程名稱后面你會看到 jettisoned 字樣。如果看到它出現在你的應用名稱后面,說明你的應用因使用太多內存而被終止了。

低內存崩潰日志看起來像這樣:

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:? 5a56599d836c4f867f6eec76afee451bf9ae5f31

OS Version:? ? ? ? ? iPhone OS 3.1.3 (7E18)

Date/Time:? ? ? ? ? 2012-10-17 21:39:06.967 -0400

Free pages:? ? ? ? 96

Wired pages:? ? ? 10558

Purgeable pages:? 0

Largest process:? Rage Masters

Processes

Name? ? ? ? ? ? ? ? UUID? ? ? ? ? ? ? ? ? ? Count resident pages

Rage Masters? ? 9320 (jettisoned) (active)

mediaserverd? ? ? 255

dataaccessd? ? ? 505

syslogd? ? ? 71

apsd? ? ? 171

securityd? ? ? 243

notifyd? ? 2027

CommCenter? ? ? 189

SpringBoard? ? 2158 (active)

accessoryd? ? ? 91

configd? ? ? 371

fairplayd? ? ? 93

mDNSResponder? ? ? 292

lockdownd? ? 1204

launchd? ? ? 72

當應用發生低內存閃退時,你必需看看應用中內存使用的方式,以及是如何處理低內存警告的。你可以使用Instruments工具中使用Allocations 和 Leaks來發現內存分配問題和內存泄漏問題。如果你不知道如何利用 Instruments 檢查內存問題,可以看看 這個教程 。

還有,別忘記虛擬內存! Instruments工具的Leaks 和 Allocations 不能跟蹤顯存使用情況。必需使用 VM Tracker 才能查看顯存使用情況。

VM Tracker 默認是關閉的。打開Instrument,手動 選中 Automatic Snapshotting 標志或者按下 Snapshot Now 按鈕。

本教程后面將會學習如何研究低內存崩潰日志。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,250評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,923評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,041評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,475評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,253評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,801評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,882評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,023評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,530評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,494評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,639評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,177評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,890評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,289評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,552評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,242評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,626評論 2 370

推薦閱讀更多精彩內容

  • 轉自http://www.raywenderlich.com/zh-hans/30818/ios應用崩潰日志揭秘 ...
    RunSnails閱讀 4,443評論 2 22
  • 異常編碼 在研究真實閃退場景之前,還有一點需要重點介紹一下:就是那些有趣的異常編碼 。 你可以在報告的異常部分——...
    中二修行者閱讀 1,819評論 0 3
  • 作為一名應用開發者,你是否有過如下經歷?經常被領導叫去,讓看哪位哪位客戶運行APP又崩潰了,感覺解決;天天被產品狗...
    繼續向前沖閱讀 2,878評論 0 9
  • 作為一名應用開發者,你是否有過如下經歷? 為確保你的應用正確無誤,在將其提交到應用商店之前,你必定進行了大量的測試...
    姚姚先生閱讀 592評論 0 1
  • 轉自:http://www.cocoachina.com/industry/20130725/6677.html ...
    mandygao閱讀 614評論 0 4