2013年9月4日 星期三

Crash Report 介紹



Crash Report簡介

iOS的app在當機的時候,操作系統通常會生成一個crash report,保存在iOS的設備上,並傳到iTunes Connect上,而crash report上面通常會有許多有用的信息,來讓我們追縱當初發生crash時的情況。一般情況下,上面會有每一個正在執行thread的back trace,所以我們能從這些資訊上面來了解到,thread在crash的當下正在做什麼事情,並且能分辨出crash在哪個thread上。

發生Crash的情況

通常最主要發生crash的情況有兩種:

1、違反Mac系統規則

2、Bug

違反iOS的規則包括在程式啟動,恢複,hangUp,程式退出,這個時候的watchDog超時,以及使用者強制退出跟low memory。

WatchDog 超時

iOS 4.x開始,離開app的時候,app不會立即停止,而是退到後台10min。
但是,如果你的app在appDelegate裡面的method耗太久的時間的話,那麼apple就有可能會終止你的app,並且產生一個crash report。
  • application:didFinishLaunchingWithOptions:
  • applicationWillResignActive:
  • applicationDidEnterBackground:
  • applicationWillEnterForeground:
  • applicationDidBecomeActive:
  • applicationWillTerminate:


如果你的app在一開始的時候就有需要跟service連結,並且你將他放置在以上的delegate下的話,建議改用non sync的方式處理,總之在以上的delegate 耗的時間越少越好,NSOperation,或是GCD都是不錯的選擇。
用户强制退出
iOS 4.x開始支持multi task,如果app 太lag卡在某一個畫面,使用者可以透過雙擊Home鍵來停止APP,  這時候apple 將會生成一個crash report。

Memory Warning

在執行中的app是擁有對記憶體的最高使用權限,但這並不表示app可以使用所有的記憶體,每一個app都只能使用一部份可用的memory 。
當memory使用到達一定的程度時,apple則會發出一個UIApplicationDidReceiveMemoryWarningNotification的通知。
此時,為了讓app能正常動作,apple會開始砍掉一些在後台的app。當所有app都被砍光了以後,如果你的app還需要更多的memory,那麼apple也會將你的app也stop掉,並且產生一個crash report。
另外補充說明一點,這時候後台的app,並不會因此而產生crash report。

BUG

這算是程式設計師最常遇到的問題了,而他的種類繁多,以下大致上歸類出幾種較常發生的問題,並且一步步的解析,希望對大家有所幫助。

Crash Report實例

//1、app 訊息
Incident Identifier: 996E2337-6952-468E-90FE-D317CE417943
CrashReporter Key:   8dda5438858aa4dddbe541af415c70e691032e33
Hardware Model:      iPod5,1
Process:         BaseProject [636]
Path:            /var/mobile/Applications/91BAE6E4-2628-4152-BB64-6452DAEF4C57/BaseProject.app/BaseProject
Identifier:      BaseProject
Version:         ??? (???)
Code Type:       ARM (Native)
Parent Process:  debugserver [635]
//2、基本訊息
Date/Time:       2013-08-28 18:57:16.567 +0800
OS Version:      iOS 6.1.3 (10B329)
Report Version:  104
//3、exception
Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Crashed Thread:  0
//4、back trace
Last Exception Backtrace:
0   CoreFoundation                0x3127629e __exceptionPreprocess + 158
1   libobjc.A.dylib               0x38f5a97a objc_exception_throw + 26
2   CoreFoundation                0x31279e02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166
3   CoreFoundation                0x3127852c ___forwarding___ + 388
4   CoreFoundation                0x311cff64 _CF_forwarding_prep_0 + 20
5   Foundation                    0x31b84272 __NSFireDelayedPerform + 446
6   CoreFoundation                0x3124b5da __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 10
7   CoreFoundation                0x3124b28c __CFRunLoopDoTimer + 268
8   CoreFoundation                0x31249efc __CFRunLoopRun + 1228
9   CoreFoundation                0x311bceb8 CFRunLoopRunSpecific + 352
10  CoreFoundation                0x311bcd44 CFRunLoopRunInMode + 100
11  GraphicsServices              0x34d842e6 GSEventRunModal + 70
12  UIKit                         0x330d22fc UIApplicationMain + 1116
13  BaseProject                     0x0007879c main (main.m:19)
14  BaseProject                     0x00076f7c start + 36

//5、thread back trace
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib        0x39458350 __pthread_kill + 8
1   libsystem_c.dylib             0x393cf11e pthread_kill + 54
2   libsystem_c.dylib             0x3940b96e abort + 90
3   libc++abi.dylib               0x389a9d4a abort_message + 70
4   libc++abi.dylib               0x389a6ff4 default_terminate() + 20
5   libobjc.A.dylib               0x38f5aa74 _objc_terminate() + 144
6   libc++abi.dylib               0x389a7078 safe_handler_caller(void (*)()) + 76
7   libc++abi.dylib               0x389a7110 std::terminate() + 16
8   libc++abi.dylib               0x389a8594 __cxa_rethrow + 84
9   libobjc.A.dylib               0x38f5a9cc objc_exception_rethrow + 8
10  CoreFoundation                0x311bcf1c CFRunLoopRunSpecific + 452
11  CoreFoundation                0x311bcd44 CFRunLoopRunInMode + 100
12  GraphicsServices              0x34d842e6 GSEventRunModal + 70
13  UIKit                         0x330d22fc UIApplicationMain + 1116
14  BaseProject                     0x0007879c main (main.m:19)
15  BaseProject                     0x00076f7c start + 36

Thread 1 name:  Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0   libsystem_kernel.dylib        0x39448648 kevent64 + 24
1   libdispatch.dylib             0x39378974 _dispatch_mgr_invoke + 792
2   libdispatch.dylib             0x39378654 _dispatch_mgr_thread$VARIANT$mp + 32

Thread 2:
0   libsystem_kernel.dylib        0x39458d98 __workq_kernreturn + 8
1   libsystem_c.dylib             0x393a6cf6 _pthread_workq_return + 14
2   libsystem_c.dylib             0x393a6a12 _pthread_wqthread + 362
3   libsystem_c.dylib             0x393a68a0 start_wqthread + 4

Thread 3:
0   libsystem_kernel.dylib        0x39458d98 __workq_kernreturn + 8
1   libsystem_c.dylib             0x393a6cf6 _pthread_workq_return + 14
2   libsystem_c.dylib             0x393a6a12 _pthread_wqthread + 362
3   libsystem_c.dylib             0x393a68a0 start_wqthread + 4

Thread 4 name:  WebThread
Thread 4:
0   libsystem_kernel.dylib        0x39447eb4 mach_msg_trap + 20
1   libsystem_kernel.dylib        0x39448048 mach_msg + 36
2   CoreFoundation                0x3124b040 __CFRunLoopServiceMachPort + 124
3   CoreFoundation                0x31249d9e __CFRunLoopRun + 878
4   CoreFoundation                0x311bceb8 CFRunLoopRunSpecific + 352
5   CoreFoundation                0x311bcd44 CFRunLoopRunInMode + 100
6   WebCore                       0x371bf500 RunWebThread(void*) + 440
7   libsystem_c.dylib             0x393b130e _pthread_start + 306
8   libsystem_c.dylib             0x393b11d4 thread_start + 4

//6、thread state
Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x3af18534
    r4: 0x00000006    r5: 0x3af18b88      r6: 0x1d840144      r7: 0x2fd8b9c4
    r8: 0x1d840120    r9: 0x00000300     r10: 0x00000000     r11: 0x000ced5c
    ip: 0x00000148    sp: 0x2fd8b9b8      lr: 0x393cf123      pc: 0x39458350
  cpsr: 0x00000010
//7、二進制映像檔
Binary Images:
   0x75000 -    0xdcfff +BaseProject armv7  <ce7c736fdbac3cdfaa3c0ff31eef0122> /var/mobile/Applications/91BAE6E4-2628-4152-BB64-6452DAEF4C57/BaseProject.app/BaseProject
  0x1eb000 -   0x1effff  AccessibilitySettingsLoader armv7  <d910faf80cd632cc8f0d9f05d3944144> /System/Library/AccessibilityBundles/AccessibilitySettingsLoader.bundle/AccessibilitySettingsLoader
0x2fe71000 - 0x2fe91fff  dyld armv7  <280610df5ed43ec7aa00629a27009302> /usr/lib/dyld
0x3047e000 - 0x3047efff  Accelerate armv7  <b68ff92e404931f3bcb6361720f77724> /System/Library/Frameworks/Accelerate.framework/Accelerate
0x3047f000 - 0x305bdfff  vImage armv7  <30522b92940d3dd184c8e46780594048> /System/Library/Frameworks/Accelerate.framework/Frameworks/vImage.framework/vImage
0x305be000 - 0x306a1fff  libBLAS.dylib armv7  <d8edada1cea133458ca779e34a3a7f88> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libBLAS.dylib
0x306a2000 - 0x30957fff  libLAPACK.dylib armv7  <9e08aead79d13043bab622402a270fba> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libLAPACK.dylib
0x30958000 - 0x309b1fff  libvDSP.dylib armv7  <09e2a5e3e9203950890ba57592523132> 
(以下略)


1、app訊息:這個是crash app的一些相關資訊


  • Incident Identifier是crash report的id,也就是上一篇提到的UUID
  • CrashReporter Key可以把他想像成是設備的ID,但並不是真的HW的ID,而只是UUID對應這個HW產生的一組ID,而這個ID通常可以拿來應用在大量的report裡面發現時常發生crash的是否是同一台設備。
  • Hardware Model就如同看到的一樣 iPod5.1,剩下就BJ4
2、基本訊息:上面記錄著crash 發生的時間跟設備的版本號,以及app的版本,可以藉由這邊知道發生問題的版本,是什麼居多。

3、exception:這邊大都記錄著crash時apple throw的exception type,舉個例子像是你看到 0x8badf00d,像是這種時候大多都是上面提到的watch dog超時被hight light了。0x8badf00d -> (8 bad food) -> (ate bad food)。
或者是SIGABRT之類的

4、back trace:這邊就是最主要的關鍵了,這邊記錄著crash的時候,當下是正在執行哪一行code。執行的順序是依次由14的start去呼叫13的main,再由13的main去呼叫UIApplicationMain以此類推回去一直到0的時候exception handler那邊發現了錯誤,而產生report。數字旁邊記錄的名字像是BaseProject這個都是二進制映像檔的名稱。

5、thread back trace:如同back trace,而這邊再詳細述敘出各個thread的back trace

6、thread state:這個是當下ARM裡面每一個暫存器的狀態。

7、二進制映像檔:這邊是印出crash的時候加載的映像檔,以及映像檔的memory stack的區間。(上一篇提到相對的address 換算的公式就是要取得crash時當下的映像檔的起始位置)

Memory 不足

Incident Identifier: 996E2337-6952-468E-90FE-D317CE417943
CrashReporter Key:   8dda5438858aa4dddbe541af415c70e691032e33
Date/Time:       2013-08-28 18:57:16.567 +0800
OS Version:      iOS 6.1.3 (10B329)
Free pages:                96
Wired pages:       10558
Purgeable pages:        0
Largest process:   BaseProject
Processes
Name                                         UUID                         Count resident pages
BaseProject                   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來分析記憶體分配問跟記憶體洩漏的問題了。

Exception Decode:

這邊在補充說明一下,通常Exception是由文字開頭,然候後面有一串16進位,這個數值就是crash的原因,在這邊可以知道crash是什麼種類的錯誤。除了如同上述提到的0x8badf00d 以外還有
  • 0xbad22222:表示VoIP應用過於頻繁而中斷。
  • 0xdeadl0cc:"Dead Look",代表後台佔用到系統資源而被中斷。
  • 0xdeadfa11:"Dead Fail",當使用者在執行app的過程中,長按關機鍵,當出現"滑動來關機"以後再長按HOME鍵,用來強制關閉app的時候產生的異常編碼。

以上,讓我們更加清楚crash檔該怎麼閱讀,下一篇會介紹如何trace,back trace的資訊。

沒有留言:

張貼留言