IOS Crash Log 分析、归类
在ios开发过程中,经常会遇到应用在开发过程中或者自己测试时不会有问题。而在安装到别人设备上,或者上传应用商店被别人下载的时候,总是被抱怨程序不定期的crash,真的很令人懊恼!
获取 iOS crash log
这时iOS crash log 派上用场了,程序的大多数crash都会记录在用户的手机中,获取crash log的方法有两种:
1. 用户把设备连接到电脑上,打开xcode-window-organizer,选中Devices-当前连接设备-Device Log,就可以查看所有当前设备的crash log,这个时候打开每一份crash的时候,发现这些文件的部分地址都会被转换成,类名,方法名和行号等。设备上的日志只用刚刚查看过都会被同步到organizer种,在LIBRARY下的Device Log可以查看
2. 如果你的应用已经上架,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。
解析ios Crash Log
如果在Itunes Connect 得到的Log文件打开查看都是十六进制的地址
Incident Identifier: 70B8BA67-3342-4354-8EC5-23B361C5A02A CrashReporter Key: 457198753f9cf1ae3862aef8ce49127acfd84425 Hardware Model: iPod5,1 Process: TestTransform [510] Path: /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform Identifier: com.TestTransform Version: 1.0 (1.0) Code Type: ARM (Native) Parent Process: launchd [1] Date/Time: 2014-04-10 09:57:27.961 +0800 OS Version: iOS 7.1 (11D167) Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Triggered by Thread: 2 Last Exception Backtrace: (0x2e71dfce 0x38e66cca 0x2e654ac4 0x57130 0x3934e82e 0x39355ad2 0x39355d24 0x39490bce 0x39490a94) Thread 0: 0 libsystem_kernel.dylib 0x39416a58 0x39416000 + 2648 1 libsystem_kernel.dylib 0x39416854 0x39416000 + 2132 2 CoreFoundation 0x2e6e8896 0x2e64a000 + 649366 3 CoreFoundation 0x2e6e7002 0x2e64a000 + 643074 4 CoreFoundation 0x2e651f4a 0x2e64a000 + 32586 5 CoreFoundation 0x2e651d2e 0x2e64a000 + 32046 6 GraphicsServices 0x3357365e 0x3356a000 + 38494 7 UIKit 0x30f9d168 0x30f2f000 + 450920 8 TestTransform 0x00061c5c 0x4f000 + 76892 9 libdyld.dylib 0x39373ab4 0x39372000 + 6836 Thread 1: 0 libsystem_kernel.dylib 0x39416808 0x39416000 + 2056 1 libdispatch.dylib 0x39358078 0x3934d000 + 45176 2 libdispatch.dylib 0x39357dfe 0x3934d000 + 44542 Thread 2 Crashed: 0 libsystem_kernel.dylib 0x394291f0 0x39416000 + 78320 1 libsystem_pthread.dylib 0x39493792 0x39490000 + 14226 2 libsystem_c.dylib 0x393d9fd8 0x39391000 + 298968 3 libc++abi.dylib 0x38708cd2 0x38708000 + 3282 4 libc++abi.dylib 0x387216e0 0x38708000 + 104160 5 libobjc.A.dylib 0x38e66f62 0x38e63000 + 16226 6 libc++abi.dylib 0x3871f1c4 0x38708000 + 94660 7 libc++abi.dylib 0x3871ea18 0x38708000 + 92696 8 libobjc.A.dylib 0x38e66d9e 0x38e63000 + 15774 9 CoreFoundation 0x2e654ac4 0x2e64a000 + 43716 10 TestTransform 0x00057132 0x4f000 + 33074 11 libdispatch.dylib 0x3934e830 0x3934d000 + 6192 12 libdispatch.dylib 0x39355ad2 0x3934d000 + 35538 13 libdispatch.dylib 0x39355d24 0x3934d000 + 36132 14 libsystem_pthread.dylib 0x39490bd0 0x39490000 + 3024 15 libsystem_pthread.dylib 0x39490a94 0x39490000 + 2708 Thread 3: 0 libsystem_kernel.dylib 0x39429c70 0x39416000 + 81008 1 libsystem_pthread.dylib 0x39490bda 0x39490000 + 3034 2 libsystem_pthread.dylib 0x39490a94 0x39490000 + 2708 Thread 2 crashed with ARM Thread State (32-bit): r0: 0x00000000 r1: 0x00000000 r2: 0x00000000 r3: 0x393ccaa9 r4: 0x00000006 r5: 0x001c5000 r6: 0x00000000 r7: 0x001c41a4 r8: 0x16e261d0 r9: 0x00000001 r10: 0x00000000 r11: 0x00000000 ip: 0x00000148 sp: 0x001c4198 lr: 0x39493797 pc: 0x394291f0 cpsr: 0x00000010 Binary Images: 0x4f000 - 0x62fff TestTransform armv7 <12a331e98ea13836b33483de64c3b1fc> /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform 0x2bec3000 - 0x2bee3fff dyld armv7 <651a31c39f71311f965f8ac44de02c88> /usr/lib/dyld 0x2d6e1000 - 0x2d6e1fff Accelerate armv7 <0424978b39f037a7b3bf9aad5b34a5b3> /System/Library/Frameworks/Accelerate.framework/Accelerate ......
如果想查看文件的庐山真面目,需要找出在上传应用时所发送的.app和.DSYM文件,切记每次发送新版本都要保留这两个文件,不然没有办法解析Crash Log的。可以先把这两个文件拷贝到桌面的某一个文件夹中,然后把.crash的文件也拷贝的同一个文件夹下。
这一解析过程需要使用Symbolicatecrash来完成,首先要找到Symbolicatecrash文件,xcode5.0在
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/
Symbolicatecrash文件独立于Xcode,可以拷到刚才放crash
log的文件夹中使用,在开始解析之前需要先进行一些校验:
1. 查看xx.app文件的uuid的方法,在命令行中输入:
$ dwarfdump --uuid xxx.app/xxx (xxx工程名)
2. 查看xx.app.dSYM文件的uuid的方法,在命令行输入:
$ dwarfdump --uuid xxx.app.dSYM (xxx工程名)
3.查看.crash的uuid,位于crash日志中的Binary Images:中的第一行。如:armv7s <13760bde0d073f1eb4d596c3df753f4b>
只有三者的uuid相同才能解析.crash文件,然后在命令行输入:
$ ./symbolicatecrash xxx.crash xxx.app.dSYM > test.log
这样可以将.crash日志转换成test.log,test.log即可读的函数文件。
输入上述命令可能会出现Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 53.这个错误。
如果出现上述错误,输入命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer,
然后继续执行./symbolicatecrash xxx.crash xxx.app.dSYM > test.log可以成功
解析后的Crash Log为:
Incident Identifier: 70B8BA67-3342-4354-8EC5-23B361C5A02A CrashReporter Key: 457198753f9cf1ae3862aef8ce49127acfd84425 Hardware Model: iPod5,1 Process: TestTransform [510] Path: /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform Identifier: com.TestTransform Version: 1.0 (1.0) Code Type: ARM (Native) Parent Process: launchd [1] Date/Time: 2014-04-10 09:57:27.961 +0800 OS Version: iOS 7.1 (11D167) Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Triggered by Thread: 2 Last Exception Backtrace: 0 CoreFoundation 0x2e71dfce __exceptionPreprocess + 126 1 libobjc.A.dylib 0x38e66cca objc_exception_throw + 34 2 CoreFoundation 0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172 3 TestTransform 0x00057130 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193) 4 libdispatch.dylib 0x3934e82e _dispatch_call_block_and_release + 6 5 libdispatch.dylib 0x39355ad2 _dispatch_root_queue_drain + 218 6 libdispatch.dylib 0x39355d24 _dispatch_worker_thread2 + 52 7 libsystem_pthread.dylib 0x39490bce _pthread_wqthread + 294 8 libsystem_pthread.dylib 0x39490a94 start_wqthread + 4 Thread 0: 0 libsystem_kernel.dylib 0x39416a58 mach_msg_trap + 20 1 libsystem_kernel.dylib 0x39416854 mach_msg + 44 2 CoreFoundation 0x2e6e8896 __CFRunLoopServiceMachPort + 150 3 CoreFoundation 0x2e6e7002 __CFRunLoopRun + 850 4 CoreFoundation 0x2e651f4a CFRunLoopRunSpecific + 518 5 CoreFoundation 0x2e651d2e CFRunLoopRunInMode + 102 6 GraphicsServices 0x3357365e GSEventRunModal + 134 7 UIKit 0x30f9d168 UIApplicationMain + 1132 8 TestTransform 0x00061c5c main (main.m:16) 9 libdyld.dylib 0x39373ab4 start + 0 Thread 1: 0 libsystem_kernel.dylib 0x39416808 kevent64 + 24 1 libdispatch.dylib 0x39358078 _dispatch_mgr_invoke + 228 2 libdispatch.dylib 0x39357dfe _dispatch_mgr_thread$VARIANT$mp + 34 Thread 2 Crashed: 0 libsystem_kernel.dylib 0x394291f0 __pthread_kill + 8 1 libsystem_pthread.dylib 0x39493792 pthread_kill + 54 2 libsystem_c.dylib 0x393d9fd8 abort + 72 3 libc++abi.dylib 0x38708cd2 abort_message + 70 4 libc++abi.dylib 0x387216e0 default_terminate_handler() + 248 5 libobjc.A.dylib 0x38e66f62 _objc_terminate() + 190 6 libc++abi.dylib 0x3871f1c4 std::__terminate(void (*)()) + 76 7 libc++abi.dylib 0x3871ea18 __cxa_throw + 112 8 libobjc.A.dylib 0x38e66d9e objc_exception_throw + 246 9 CoreFoundation 0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172 10 TestTransform 0x00057132 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193) 11 libdispatch.dylib 0x3934e830 _dispatch_call_block_and_release + 8 12 libdispatch.dylib 0x39355ad2 _dispatch_root_queue_drain + 218 13 libdispatch.dylib 0x39355d24 _dispatch_worker_thread2 + 52 14 libsystem_pthread.dylib 0x39490bd0 _pthread_wqthread + 296 15 libsystem_pthread.dylib 0x39490a94 start_wqthread + 4 Thread 3: 0 libsystem_kernel.dylib 0x39429c70 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x39490bda _pthread_wqthread + 306 2 libsystem_pthread.dylib 0x39490a94 start_wqthread + 4 Thread 2 crashed with ARM Thread State (32-bit): r0: 0x00000000 r1: 0x00000000 r2: 0x00000000 r3: 0x393ccaa9 r4: 0x00000006 r5: 0x001c5000 r6: 0x00000000 r7: 0x001c41a4 r8: 0x16e261d0 r9: 0x00000001 r10: 0x00000000 r11: 0x00000000 ip: 0x00000148 sp: 0x001c4198 lr: 0x39493797 pc: 0x394291f0 cpsr: 0x00000010 Binary Images: 0x4f000 - 0x62fff TestTransform armv7 <12a331e98ea13836b33483de64c3b1fc> /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform 0x2bec3000 - 0x2bee3fff dyld armv7 <651a31c39f71311f965f8ac44de02c88> /usr/lib/dyld 0x2d6e1000 - 0x2d6e1fff Accelerate armv7 <0424978b39f037a7b3bf9aad5b34a5b3> /System/Library/Frameworks/Accelerate.framework/Accelerate ......
这时候发现之前的一些行首为项目名 后面的地址变成的方面调用+行号。
此外,还可以在上面三个uuid对应的情况下解析某一个地址的内容
$ atos -o xxx.app/xxx -arch armv7 0x38ad42f9 0x38ad42f9 0x38ad42f9(多个16进制地址,使用空格分开)---方法一 $ dwarfdump –lookup 0x000036d2 –arch armv6 xxx.app.dSYM ---方法二
分析ios Crash Log:
Incident Identifier:当前crash的 id,可以区分不同的crash事件
CrashReporter Key:
当前设备的id,可以判断crash在某一设备上出现的频率
Hardware Model: 设备型号
Process:
当前应用的名称,后面中括号中为当前的应用在系统中的进程id
Path:
当前应用在设备中的路径
Identifier:
bundle id
Version:
应用版本号
Code Type:
(还不清楚)
Date/Time:
crash事件 时间
OS Version:
当前系统版本
Exception Type: 异常类型
Exception
Codes: 异常出错的代码(常见代码有以下几种)
0x8badf00d错误码:Watchdog超时,意为“ate bad food”。
0xdeadfa11错误码:用户强制退出,意为“dead fall”。
0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。
0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。
0xc00010ff错误码:因为太烫了被干掉,意为“cool off”。
0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为“dead lock”。
Triggered by Thread: 在某一个线程出了问题导致crash,Thread 0
为主线程、其它的都为子线程
Last Exception Backtrace:
最后异常回溯,一般根据这个代码就能找到crash的具体问题
Crash Log分类:
如果所有的CrashLog已经被采集下来了,为了避免重复解决相同的bug,这个时候就需要所有的CrashLog分类,通过上面已有的信息,就可以对CrashLog做如下的分类控制:
1. 通过设备id查找当前设备上出现的crash(通过CrashReporter Key);
2.
查找所有在iphone5上出现的crash(通过Hardware Model);
3. 查找所有在ios7.1上出现的crash(通过OS
Version);
4. 查找所有在应用1.0版本上出现的crash(通过 Version);
5.
查看在某一个时间段内出现的crash(通过 Date/Time);
6. 查找所有因为内存问题出现的crash (通过 Exception
Type);
7. 查找在主线程出现crash的问题(Triggered by Thread == 0);
8.
对上述条件的组合查询;
当然做主要的时对crash的分类,判断两个crash是不是属于同一个(或同一类)crash:
1. 通过Triggered by
Thread字段判断当前两个crash是不是同时都在主线程(或同时都在子线程);
2. 判断当前两个crash的Exception
Type和Exception Codes是否相同;
3. 如果有Last Exception Backtrace:字段,执行 4. 5 步;
4.
可以先判断Last Exception
Backtrace:栈上的行数是不是一样(如果在解析之前,每一行用一个地址表示),不一样则认为不是同一个crash;
解析前:
Last Exception Backtrace: (0x2e71dfce 0x38e66cca 0x2e654ac4 0x57130 0x3934e82e 0x39355ad2 0x39355d24 0x39490bce 0x39490a94)
解析后:
Last Exception Backtrace: 0 CoreFoundation 0x2e71dfce __exceptionPreprocess + 126 1 libobjc.A.dylib 0x38e66cca objc_exception_throw + 34 2 CoreFoundation 0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172 3 TestTransform 0x00057130 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193) 4 libdispatch.dylib 0x3934e82e _dispatch_call_block_and_release + 6 5 libdispatch.dylib 0x39355ad2 _dispatch_root_queue_drain + 218 6 libdispatch.dylib 0x39355d24 _dispatch_worker_thread2 + 52 7 libsystem_pthread.dylib 0x39490bce _pthread_wqthread + 294 8 libsystem_pthread.dylib 0x39490a94 start_wqthread + 4
5.
先由第一个地址开始比较逐个比较(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到发现某一个地址不一样,使用dwarfdump命令分别将两个地址解析。得到两个crash当前调用的方法名称和分别位于文件的行号,通过得到的信息在进行比较,然后终止比较,如果一样,则认为当前两个crash为同一原因,对比结束;
6.
如果没有Last Exception Backtrace:字段,执行 7. 8. 步;
7. 先通过Triggered by
Thread字段找到两个crashLog分别对应的栈,比较栈上的行数是不是一样,不一样则认为不是同一个crash;
8.
每一行对应一个地址,先由第一个地址开始比较(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到发现某一个地址不一样,使用dwarfdump命令分别将两个地址解析。得到两个crash当前调用的方法名称和分别位于文件的行号,通过得到的信息在进行比较,然后终止比较,如果一样,则认为当前两个crash为同一原因,对比结束;
附上关于对ios crash log 介绍比较全面的连接,网站有些不稳定可能打不开,看人品吧,哈哈!!
http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF%97%E6%8F%AD%E7%A7%98
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。