在日常开发中,我们难免遇到崩溃.如果是在开发过程中,我们可以直接通过xcode来找到问题所在.如果是在测试的时候崩溃,我们也可以轻易的通过测试机导出crash进行问题定位. 可是一旦当产品上线之后.这一切就变得不那么容易了.庆幸的是市场上已经出现了一些比较好的第三方crash统计服务比如bugly. 可以让我轻松了解到crash时的堆栈信息. 但是bugly也有符号化不到位的情况. 比如:
那么在这种情况下我们应该怎么办呢?
崩溃日志符号化
使用xcode符号化
条件: (需要崩溃手机)
如果发生崩溃的手机在手边.可以连上电脑 在xcode中的organizer>device中直接查看符号化好的日志.
优点: 操作简单
缺点: 如果崩溃日志较多 还需要崩溃时间才能确定是哪个crash文件. crash不好统计
使用symbolicatecrash符号化
条件: crash文件 dsYM文件 symbolicatecrash
symbolicatecrash 位置
1 (/Applications/Xcode.app/Contents/ShareDVTFoundation.framework/Versions/A/Resources/symbolicatecrashdFrameworks/)
方法: 将三个文件放在同级下 然后打开终端 进入文件夹目录下
1 . 设置环境变量
1 export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
2 . 符号化
12 ### symbol.crash 就是最后符号化好的文件 ###../symbolicatecrash ../.crash ../.dsym > ../symbol.crash
优点:操作简单
缺点:适合针对单个crash 文件符号化
使用atos命令符号化
条件: dSYM 和堆栈信息
使用 grep 命令 获取该模块的 指令集和加载起始地址
1 grep "name armv" ../*.crash
然后用获得的指令集(armv7) 和起始地址(0x4000) 来符号化
12345 xcrun atos -o ../.dsYM/../name -l 0x4000(起始地址) -arch -armv7(指令集) //输入目标地址 0x00352aee //得到结果 -[UIScrollView(UITouch) touchesEnded:withEvent:] (in appName) (UIScrollView+UITouch.h:26)
注意 模块只能定位到本模块的位置 不能越层 如:
AFN.framework.dSYM 只能定位到AFN内的目标地址位置
appName.app.dSYM 只能定位到app内代码的地址位置
优点: 只需要堆栈信息 和符号表就可以. 可以在获取不到Crash文件 但在bugly等第三方统计中获得了堆栈信息的情况下使用.
缺点: 一次只能符号化一行,比较繁琐.(可以作为bugly符号化不完全情况下的补充.)
有兴趣的可以实际动手操作下:
xcode自带atos脚本: symbolicatecrash 下载
crash文件 : demoAPP.crash 下载
符号表: demoAPP.app.dSYM 下载
第三方模块符号表 RBPlayer.framework.dSYM 下载
crash文件组成分析
让我们看一下一个实际的 crash 文件组成
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 ### 1.进程信息 ###Incident Identifier: CDDADF33-6F8A-44B3-90D1-52D9095ADA0CCrashReporter Key: ed6929203307e230288ce2a758bd7099d3a52e15Hardware Model: iPhone5,2Process: demoApp [9806]Path: /private/var/containers/Bundle/Application/0C5CCF0C-6A7F-4864-BD5A-0765725E0CCB/demoApp.app/demoAppIdentifier: com.yimiao100.demoAppVersion: 6 (1.6)Code Type: ARM (Native)Role: ForegroundParent Process: launchd [1]Coalition: com.yimiao100.demoApp [3588]### 2.基本信息 ###Date/Time: 2017-05-10 10:37:51.2003 +0800Launch Time: 2017-05-10 10:36:26.0000 +0800OS Version: iPhone OS 10.3.1 (14E304)Report Version: 104### 3.异常信息 ###Exception Type: EXC_CRASH (SIGABRT)Exception Codes: 0x0000000000000000, 0x0000000000000000Exception Note: EXC_CORPSE_NOTIFYTriggered by Thread: 0Application Specific Information:abort() calledFiltered syslog:None foundLast Exception Backtrace:(0x1ceefb38 0x1c177062 0x1ceefa80 0x1fd6f826 0x1fd6f9de 0x1fd70044 0x148a244 0x14813e4 0x1ce9bdb4 0x1ce9b6f4 0x1ce9b4dc 0x1cef6304 0x1cdff030 0x1d74c0a8 0x1d750b26 0x147f440 0x237bff76 0x237c0622 0x237c1644 0x1c5bd792 0x1c5bd77e 0x1c5c1d00 0x1ceabd64 0x1cea9e14 0x1cdfd0ea 0x1cdfcf0c 0x1e5a7b3c 0x22181e7e 0x10b2a8 0x1c5ea4e6)### 4.线程回溯 ###Thread 0 name: Dispatch queue: com.apple.main-thread### Crash调用堆栈 ###Thread 0 Crashed:0 libsystem_kernel.dylib 0x1c6bdacc 0x1c6a8000 + 887801 libsystem_pthread.dylib 0x1c7760f6 0x1c771000 + 207262 libsystem_c.dylib 0x1c65295a 0x1c608000 + 3054983 libc++abi.dylib 0x1c157708 0x1c156000 + 58964 libc++abi.dylib 0x1c16e552 0x1c156000 + 996665 libobjc.A.dylib 0x1c17731e 0x1c170000 + 294706 demoApp 0x005b6e78 0x44000 + 57135287 libc++abi.dylib 0x1c16b98e 0x1c156000 + 884628 libc++abi.dylib 0x1c16b1a2 0x1c156000 + 864349 libobjc.A.dylib 0x1c177138 0x1c170000 + 2898410 CoreFoundation 0x1ceefa84 0x1cdf5000 + 102669211 QuartzCore 0x1fd6f82a 0x1fc7c000 + 99741812 QuartzCore 0x1fd6f9e2 0x1fc7c000 + 99785813 QuartzCore 0x1fd70048 0x1fc7c000 + 99949614 RBPlayer 0x0148a248 0x1477000 + 7840815 RBPlayer 0x014813e8 0x1477000 + 4196016 CoreFoundation 0x1ce9bdb8 0x1cdf5000 + 68344817 CoreFoundation 0x1ce9b6f8 0x1cdf5000 + 68172018 CoreFoundation 0x1ce9b4e0 0x1cdf5000 + 68118419 CoreFoundation 0x1cef6308 0x1cdf5000 + 105344820 CoreFoundation 0x1cdff034 0x1cdf5000 + 4101221 Foundation 0x1d74c0ac 0x1d746000 + 2474822 Foundation 0x1d750b2a 0x1d746000 + 4381823 RBPlayer 0x0147f444 0x1477000 + 3386024 AVFoundation 0x237bff7a 0x23759000 + 42175425 AVFoundation 0x237c0626 0x23759000 + 42346226 AVFoundation 0x237c1648 0x23759000 + 42759227 libdispatch.dylib 0x1c5bd796 0x1c5bc000 + 603828 libdispatch.dylib 0x1c5bd782 0x1c5bc000 + 601829 libdispatch.dylib 0x1c5c1d04 0x1c5bc000 + 2381230 CoreFoundation 0x1ceabd68 0x1cdf5000 + 74890431 CoreFoundation 0x1cea9e18 0x1cdf5000 + 74088832 CoreFoundation 0x1cdfd0ee 0x1cdf5000 + 3300633 CoreFoundation 0x1cdfcf10 0x1cdf5000 + 3252834 GraphicsServices 0x1e5a7b40 0x1e59e000 + 3974435 UIKit 0x22181e82 0x22110000 + 46656236 demoApp 0x0010b2ac 0x44000 + 81578837 libdyld.dylib 0x1c5ea4ea 0x1c5e7000 + 13546### 其他线程 ###Thread 1 name: Dispatch queue: com.apple.root.default-qosThread 1:0 libsystem_kernel.dylib 0x1c6bde7c 0x1c6a8000 + 897241 libsystem_c.dylib 0x1c6120e8 0x1c608000 + 411922 Foundation 0x1d834c36 0x1d746000 + 9779743 demoApp 0x00228310 0x44000 + 19832484 libdispatch.dylib 0x1c5bd796 0x1c5bc000 + 60385 libdispatch.dylib 0x1c5cab1c 0x1c5bc000 + 601886 libdispatch.dylib 0x1c5cc1b4 0x1c5bc000 + 659727 libdispatch.dylib 0x1c5cc00e 0x1c5bc000 + 655508 libsystem_pthread.dylib 0x1c7728ec 0x1c771000 + 63809 libsystem_pthread.dylib 0x1c7724cc 0x1c771000 + 5324Thread 2 name: com.apple.uikit.eventfetch-threadThread 2:0 libsystem_kernel.dylib 0x1c6a8900 0x1c6a8000 + 23041 libsystem_kernel.dylib 0x1c6a86e0 0x1c6a8000 + 17602 CoreFoundation 0x1ceabbe2 0x1cdf5000 + 7485143 CoreFoundation 0x1ceaa064 0x1cdf5000 + 741476...Thread 3 name: com.apple.NSURLConnectionLoaderThread 3:0 libsystem_kernel.dylib 0x1c6a8900 0x1c6a8000 + 23041 libsystem_kernel.dylib 0x1c6a86e0 0x1c6a8000 + 17602 CoreFoundation 0x1ceabbe2 0x1cdf5000 + 7485143 CoreFoundation 0x1ceaa064 0x1cdf5000 + 7414764 CoreFoundation 0x1cdfd0ee 0x1cdf5000 + 33006...... ...Thread 0 crashed with ARM Thread State (32-bit): r0: 0x00000000 r1: 0x00000000 r2: 0x00000000 r3: 0x0000006e r4: 0x00000006 r5: 0x3a697e40 r6: 0x397d430c r7: 0x00c88044 r8: 0x00000002 r9: 0x00000000 r10: 0x40000000 r11: 0x158ee214 ip: 0x00000148 sp: 0x00c88038 lr: 0x1c7760f7 pc: 0x1c6bdacc cpsr: 0x00000010### 5.动态库信息 ###Binary Images:0x44000 - 0x85ffff demoApp armv7 <4d8140e3978f35d29c938c2659aa766d>/var/containers/Bundle/Application/0C5CCF0C-6A7F-4864-BD5A-0765725E0CCB/demoApp.app/demoApp0xa4d000 - 0xa78fff AFNetworking armv7 /var/containers/Bundle/Application/0C5CCF0C-6A7F-4864-BD5A-0765725E0CCB/demoApp.app/Frameworks/AFNetworking.framework/AFNetworking0x1477000 - 0x1496fff RBPlayer armv7 /var/containers/Bundle/Application/0C5CCF0C-6A7F-4864-BD5A-0765725E0CCB/demoApp.app/Frameworks/RBPlayer.framework/RBPlayerEOF
进程信息
第一部分是闪退进程的相关信息。
Incident Identifier
是崩溃报告的唯一标识符。
CrashReporter Key
是与设备标识相对应的唯一键值。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上。
Hardware Model
标识设备类型。 如果很多崩溃日志都是来自相同的设备类型,说明应用只在某特定类型的设备上有问题。上面的日志里,崩溃日志产生的设备是iPhone5。
Process
是应用名称。中括号里面的数字是闪退时应用的进程ID。
基本信息
Version
APP的版本号
OS Version
iOS操作系统版本号 iPhone OS 10.3.1 (14E304)
10.3.1:系统版本
14E304:build号
这里要所以下build号。每个系统版本号有可能会对应多个build号。如苹果发布的10.3.1会有几个版本,如:电信版本、联通版本等。build号我们后面对日志符号化的时候会用到。
异常信息
在这部分,你可以看到闪退发生时抛出的异常类型。还能看到异常编码和抛出异常的线程。根据崩溃报告类型的不同,在这部分你还能看到一些另外的信息。
Crashed Thread
crash线程号。可以根据这个编号找到对应的crash调用堆栈,当前crash线程的编号为0,所以我们可以直接找到crash线程的堆栈信息:
12345678910111213141516171819202122232425262728293031323334353637383940 Thread 0 name: Dispatch queue: com.apple.main-threadThread 0 Crashed:0 libsystem_kernel.dylib 0x1c6bdacc 0x1c6a8000 + 887801 libsystem_pthread.dylib 0x1c7760f6 0x1c771000 + 207262 libsystem_c.dylib 0x1c65295a 0x1c608000 + 3054983 libc++abi.dylib 0x1c157708 0x1c156000 + 58964 libc++abi.dylib 0x1c16e552 0x1c156000 + 996665 libobjc.A.dylib 0x1c17731e 0x1c170000 + 294706 demoApp 0x005b6e78 0x44000 + 57135287 libc++abi.dylib 0x1c16b98e 0x1c156000 + 884628 libc++abi.dylib 0x1c16b1a2 0x1c156000 + 864349 libobjc.A.dylib 0x1c177138 0x1c170000 + 2898410 CoreFoundation 0x1ceefa84 0x1cdf5000 + 102669211 QuartzCore 0x1fd6f82a 0x1fc7c000 + 99741812 QuartzCore 0x1fd6f9e2 0x1fc7c000 + 99785813 QuartzCore 0x1fd70048 0x1fc7c000 + 99949614 RBPlayer 0x0148a248 0x1477000 + 7840815 RBPlayer 0x014813e8 0x1477000 + 4196016 CoreFoundation 0x1ce9bdb8 0x1cdf5000 + 68344817 CoreFoundation 0x1ce9b6f8 0x1cdf5000 + 68172018 CoreFoundation 0x1ce9b4e0 0x1cdf5000 + 68118419 CoreFoundation 0x1cef6308 0x1cdf5000 + 105344820 CoreFoundation 0x1cdff034 0x1cdf5000 + 4101221 Foundation 0x1d74c0ac 0x1d746000 + 2474822 Foundation 0x1d750b2a 0x1d746000 + 4381823 RBPlayer 0x0147f444 0x1477000 + 3386024 AVFoundation 0x237bff7a 0x23759000 + 42175425 AVFoundation 0x237c0626 0x23759000 + 42346226 AVFoundation 0x237c1648 0x23759000 + 42759227 libdispatch.dylib 0x1c5bd796 0x1c5bc000 + 603828 libdispatch.dylib 0x1c5bd782 0x1c5bc000 + 601829 libdispatch.dylib 0x1c5c1d04 0x1c5bc000 + 2381230 CoreFoundation 0x1ceabd68 0x1cdf5000 + 74890431 CoreFoundation 0x1cea9e18 0x1cdf5000 + 74088832 CoreFoundation 0x1cdfd0ee 0x1cdf5000 + 3300633 CoreFoundation 0x1cdfcf10 0x1cdf5000 + 3252834 GraphicsServices 0x1e5a7b40 0x1e59e000 + 3974435 UIKit 0x22181e82 0x22110000 + 46656236 demoApp 0x0010b2ac 0x44000 + 81578837 libdyld.dylib 0x1c5ea4ea 0x1c5e7000 + 13546
看下面这行日志:
1 6 demoApp 0x005b6e78 0x44000 + 5713528
这条调用栈包括下面四部分:
1.模块号:这里是6
2.二进制库名:这里是demoApp
3.调用方法的地址:这里是0x005b6e78
4.第四部分分为两列,基地址和偏移地址。此处基地址为0x66000,偏移地址为19244367。基地址指向crash的模块(也是模块的load地址)如UIKit。偏移地址指向crash代码的行数。如何转换我们后面讨论。这些信息都保存在dsym文件中。
动态库信息
这些信息包括动态库名称、UUID、模块起始地址、模块结束地址、指令集种类、安装路径等信息。
这些信息都是在符号化堆栈用到的。后面我们讨论怎么用。
特别注意
注意: 你必需同时保留应用二进制文件和.dSYM文件才能将崩溃日志完整符号化。每次提交到iTunes Connect的构建都必需归档保存。
.dSYM文件和二进制文件是特定绑定于每一次构建和后续构建的,即使来自相同的源代码文件,每一次构建也与其他构建不同,不能相互替换。
如果你使用Build 和 Archive 命令,这些文件会自动放在适当位置。 如果不是使用Build 和 Archive命令,最好放到单独的文件夹保存。
附录
符号化好的crash文件
12345678910111213141516171819202122232425262728293031 Last Exception Backtrace:0 CoreFoundation 0x1ceefb38 __exceptionPreprocess + 1241 libobjc.A.dylib 0x1c177062 objc_exception_throw + 342 CoreFoundation 0x1ceefa80 +[NSException raise:format:] + 1043 QuartzCore 0x1fd6f826 CA::Layer::set_position(CA::Vec2 const&, bool) + 2344 QuartzCore 0x1fd6f9de -[CALayer setPosition:] + 505 QuartzCore 0x1fd70044 -[CALayer setFrame:] + 4846 RBPlayer 0x01483244 -[RBPlayerSlider setValue:] (RBPlayerSlider.m:194)7 RBPlayer 0x0147a3e4 -[RBPlayerBottomMask playerUpdateCurrentSeconds] (RBPlayerBottomMask.m:111)8 CoreFoundation 0x1ce9bdb4 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 69 CoreFoundation 0x1ce9b6f4 _CFXRegistrationPost + 37810 CoreFoundation 0x1ce9b4dc ___CFXNotificationPost_block_invoke + 3611 CoreFoundation 0x1cef6304 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 123812 CoreFoundation 0x1cdff030 _CFXNotificationPost + 53613 Foundation 0x1d74c0a8 -[NSNotificationCenter postNotificationName:object:userInfo:] + 6214 Foundation 0x1d750b26 -[NSNotificationCenter postNotificationName:object:] + 2615 RBPlayer 0x01478440 __32-[RBCorePlayer addTimerObserver]_block_invoke (RBCorePlayer.m:243)16 AVFoundation 0x237bff76 -[AVPeriodicTimebaseObserver _fireBlockForTime:] + 6417 AVFoundation 0x237c0622 -[AVPeriodicTimebaseObserver _handleTimeDiscontinuity] + 23418 AVFoundation 0x237c1644 __AVTimebaseObserver_timebaseNotificationCallback_block_invoke + 12219 libdispatch.dylib 0x1c5bd792 _dispatch_call_block_and_release + 620 libdispatch.dylib 0x1c5bd77e _dispatch_client_callout + 1821 libdispatch.dylib 0x1c5c1d00 _dispatch_main_queue_callback_4CF + 89822 CoreFoundation 0x1ceabd64 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 423 CoreFoundation 0x1cea9e14 __CFRunLoopRun + 84424 CoreFoundation 0x1cdfd0ea CFRunLoopRunSpecific + 46625 CoreFoundation 0x1cdfcf0c CFRunLoopRunInMode + 10026 GraphicsServices 0x1e5a7b3c GSEventRunModal + 7627 UIKit 0x22181e7e UIApplicationMain + 14628 VaccineSale 0x001042a8 main (main.m:15)29 libdyld.dylib 0x1c5ea4e6 _dyld_process_info_notify_release + 26
从符号化完的堆栈信息可以清楚的看出 崩溃是由 RBPlayer类 RBPlayerSlider文件 setValue:方法中 第194行引起的. 该行对layer的frame和position进行赋值操作时引起了崩溃.
–原创所有,转载请注明出处