iOS崩潰日誌分析

崩潰日誌的產生

iOS中運行App過程中如果發生程序崩潰,會生成一個崩潰日誌文件。這個文件會保存的特定系統目錄下,擴展名是crash。當手機連接到iTunes時,會將該文件同步到電腦上。

在Mac系統中這些文件會同步到“~/Library/Logs/CrashReporter/MobileDevice”下。

而在Windows系統中會同步到“C:\Users\\AppData\Roaming\Apple computer\Logs\CrashReporter/MobileDevice”(Vista或以上)或“C:\Documents and Settings\\Application Data\Apple computer\Logs\CrashReporter”(XP)。

崩潰日誌的上傳

iOS中崩潰日誌是可以上傳的App Store的服務器,並由開發者查看的。用戶可以通過系統設置中的“通用-診斷與用量”來設定是否上傳崩潰日誌。同時開發者也可以通過捕獲異常信號自己定製異常上報。

崩潰日誌的格式

一般崩潰日誌頭部有如下字段

1
2
3
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x20000008
Crashed Thread:  0

其中Exception Type是異常類型,Exception Codes是異常代碼。Crashed Thread指示異常的線程編號。上面表示Crash的線程編號是0(主線程的線程編號是0)。

看崩潰日誌時一般要分兩種情況,一種是內存、CPU的系統錯誤,如內存訪問錯誤、除零異常等。另外一種是程序通過寫代碼拋出的異常,即代碼中通過throw關鍵字拋出的異常。程序拋出的異常是可以捕獲並處理的,如果沒有捕獲,就會Crash,並生成崩潰日誌。這兩種在日誌中有一些細微的差別。

一般內存等系統異常Crash線程信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x3624cf78 objc_msgSend + 16
1   QQYanChu                        0x0000d92a -[QYServerInterface connectionDidFinishLoading:] (QYServerInterface.m:328)
2   Foundation                      0x30d03c22 __65-[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]_block_invoke_0 + 10
3   Foundation                      0x30c5b6d2 -[NSURLConnectionInternalConnection invokeForDelegate:] + 22
4   Foundation                      0x30c5b69c -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 192
5   Foundation                      0x30c5b5be -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 54
6   CFNetwork                       0x338077ee URLConnectionClient::_clientDidFinishLoading(URLConnectionClient::ClientConnectionEventQueue*) + 186
7   CFNetwork                       0x337fc49e URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) + 418
8   CFNetwork                       0x337fc592 URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload(XConnectionEventInfo<XClientEvent, XClientEventParams>*, long) + 662
9   CFNetwork                       0x337fc19c URLConnectionClient::processEvents() + 100
10  CFNetwork                       0x337fc0d2 MultiplexerSource::perform() + 150
11  CoreFoundation                  0x34dffacc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
12  CoreFoundation                  0x34dff298 __CFRunLoopDoSources0 + 208
13  CoreFoundation                  0x34dfe03e __CFRunLoopRun + 646
14  CoreFoundation                  0x34d8149e CFRunLoopRunSpecific + 294
15  CoreFoundation                  0x34d81366 CFRunLoopRunInMode + 98
16  GraphicsServices                0x3607d432 GSEventRunModal + 130
17  UIKit                           0x31e77e76 UIApplicationMain + 1074
18  QQYanChu                        0x0000feea main (main.m:39)
19  QQYanChu                        0x00007ed4 start + 32

第一列是編號,表示堆棧中函數調用的嵌套順序。最上面就是崩潰發生的函數,往下面看就可以看到我們的代碼。第二列是堆棧中函數定義的位置,有的是在動態庫或Framework中定義的,有的是我們的App定義的,如QQYanChu就是我們的App可執行文件,另外你還可以看到其他的動態庫等,一般我們關注自己的QQYanChu的就行了。 如上面的例子就是在-[QYServerInterface connectionDidFinishLoading:] 這個調用中掛的。一般這個信息還會包含代碼文件和說對應的行號,如上面紅色部分就是說崩潰在QYServerInterface.m的328行。這就可以方便我們快速定位問題。

下面是程序拋出的異常的日誌。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Last Exception Backtrace:
0   CoreFoundation                  0x3425929e __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x33a2b97a objc_exception_throw + 26
2   CoreFoundation                  0x3425ce02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166
3   CoreFoundation                  0x3425b52c ___forwarding___ + 388
4   CoreFoundation                  0x341b2f64 _CF_forwarding_prep_0 + 20
5   QQYanChu                        0x000ef372 -[QYUser staticDataFetcher:fetchedData:] (QYUser.m:168)
6   QQYanChu                        0x001ee9f2 -[QStaticDataFetcher successWithData:] + 94
7   QQYanChu                        0x001efb44 -[QStaticDataFetcher sendDelegateMessageWithLocalData] + 220
8   Foundation                      0x39256a6a __NSFireDelayedPerform + 446
9   CoreFoundation                  0x3422e5da __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 10
10  CoreFoundation                  0x3422e28c __CFRunLoopDoTimer + 268
11  CoreFoundation                  0x3422cefc __CFRunLoopRun + 1228
12  CoreFoundation                  0x3419feb8 CFRunLoopRunSpecific + 352
13  CoreFoundation                  0x3419fd44 CFRunLoopRunInMode + 100
14  GraphicsServices                0x34f082e6 GSEventRunModal + 70
15  UIKit                           0x36de52fc UIApplicationMain + 1116
16  QQYanChu                        0x000fcfc0 main (main.m:39)
17  QQYanChu                        0x000ee4d4 start + 36
 
 
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x32f28350 __pthread_kill + 8
1   libsystem_c.dylib               0x3830311e pthread_kill + 54
2   libsystem_c.dylib               0x3833f96e abort + 90
3   libc++abi.dylib                 0x38e35d4a abort_message + 70
4   libc++abi.dylib                 0x38e32ff4 default_terminate() + 20
5   libobjc.A.dylib                 0x33a2ba74 _objc_terminate() + 144
6   libc++abi.dylib                 0x38e33078 safe_handler_caller(void (*)()) + 76
7   libc++abi.dylib                 0x38e33110 std::terminate() + 16
8   libc++abi.dylib                 0x38e34594 __cxa_rethrow + 84
9   libobjc.A.dylib                 0x33a2b9cc objc_exception_rethrow + 8
10  CoreFoundation                  0x3419ff1c CFRunLoopRunSpecific + 452
11  CoreFoundation                  0x3419fd44 CFRunLoopRunInMode + 100
12  GraphicsServices                0x34f082e6 GSEventRunModal + 70
13  UIKit                           0x36de52fc UIApplicationMain + 1116
14  QQYanChu                        0x000fcfc0 main (main.m:39)
15  QQYanChu                        0x000ee4d4 start + 36

可以看出相比系統異常日誌中多出了Last Exception Backtrace字段。上面是線程0崩潰的,而線程0只調用的abort。這是我們要看Last Exception Backtrace這裏的堆棧,這個堆棧是拋出異常時的線程當時的堆棧情況,這個信息纔是有意義的。在我們程序拋出異常後,系統會執行一系列相關邏輯後調用abort異常結束程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章