使用dSYM分析App崩溃日志
前言
我们在开发App过程中,因为连接到控制台,所以遇到问题会很容易找到问题代码。但是对于线上的App出现Crash的时候,我们不可能通过这种方式,也不现实,所以我们只能通过收集Crash信息,来解决Bug。而这种收集Crash信息并且分析定位到具体代码的第三方SDK很多。但是今天我们来自己实现一下。
收集 Crash 信息
Apple提供了NSException类来帮助我们收集异常信息。
NSException is used to implement exception handling and contains information about an exception — Apple Documentation.
点击这里来查看官方文档具体内容。
我们的确可以通过NSException来收集信息,但是,我们怎么把这个信息保存下来,并且上传到我们后台服务器,收集起来呢。这就需要用到另一个函数:NSUncaughtExceptionHandler
Sets the top-level error-handling function where you can perform last-minute logging before the program terminates.http://www.90168.org/
意思就是我们可以在App异常退出的之前有一分钟的时间来处理异常信息,利用这段时间,我们可以把Crash信息写入本地,也可以上传到服务器,但是考虑到网络阻塞原因,我们可能在这一分钟不能操作完毕,所以我们把上传放到下一次App启动时执行。
具体的代码如下:
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 |
- (void)lyCarshLog { [self uploadExceptionLog]; NSSetUncaughtExceptionHandler(&catchExceptionLog); } - (void)uploadExceptionLog { if (log != nil) { // 在这里上传 Crash 信息,上传完毕后要记得清空。 } } void catchExceptionLog(NSException *exception) { // 获取 Crash 信息 NSArray *symbols = [exception callStackSymbols]; NSString *reason = [exception reason]; NSString *name = [exception name]; NSDictionary *userInfo = [exception userInfo]; //... /*另外,我们可能需要一些别的信息,比如说发生 Crash 的设备的系统版本,设备型号,App的版本号*/ struct utsname systemInfo; // 需要导入`sys/utsname.h`头文件。 uname(&systemInfo); NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; NSDictionary *appInfo = [[NSBundle mainBundle] infoDictionary]; NSString *appVersion = [appInfo objectForKey:@"CFBundleShortVersionString"]; NSString *result = [NSString stringWithFormat:@"CarshReason = %@ \n name = %@ \n userInfo = %@ \n log = %@ \n systemVersion = %f \n deviceInfo = %@ \n appVersion = %@ ",reason,name,userInfo,symbols,[UIDevice currentDevice].systemVersion.floatValue,deviceString,appVersion]; // 把 result 写入本地。 }
|
Crash信息至此已经收集完毕,等待下次App启动的时候,我们把本地的Crash信息上传到服务器就OK了。
处理 Crash 信息 - 符号化(Fully Symbolicated)
我们得到的信息可能如下(Partially Symbolicated): 
Tips: 堆栈跟踪是
自下而上展示的,也就是最先调用的方法在最下面。
每行信息中包含的信息: 
其中:
Binary name表明代码所在App或者Framework的位置。比如:line 0 是在CoreFoundation中,line 3 在CrashDemo中…Address方法的内存地址。Class name当前的类名。Method name当前调用的方法名。Offset相对加载地址/基地址(load address)的偏移量。
我们得到这个半符号化(Partially Symbolicated)的日志对我们分析Crash原因的帮助很有限,因为我们可能只能知道__NSArrayI objectAtIndex:调用出现了问题,但是不能定位到具体代码。所以我们要把它完全符号化(Fully Symbolicated)。
dSYM
我们需要借助dSYM来帮助我们完成符号化,对于dSYM文件的获取,我们可以通过多种方法,我这里只说一种:
先打开Xcode,Windows->Organize->找到对应的app包,然后右键->Show in finder,找到appName. xcarchive->显示包内容->把dSYMs拷贝出来(或者就在里面操作)。
atos
The atos command converts numeric addresses to their symbolic equivalents
我们使用atos命令来完成符号化,具体命令如下: $ atos -arch <Binary Architecture> -o <Path to dSYM file>/Contents/Resources/DWARF/<binary image name> -l <load address> <address to symbolicate> 其中:
- Binary Architecture:
arm64、armv6、armv7armv7s根据自己的情况来写。 - Path to dSYM file: dSYM文件的路径。
- binary image name: 你工程的名字。
- load address: 基地址,如果我们的崩溃日志中没有这个信息(比如上面的Crash信息中就没有包含),就需要我们手动去计算这个
load address:laod address = address to symbolicate - offset,比如:0x0000000102838119转化为十进制为4337139993,再减去偏移量265,为4337139728,在转化为十六进制0x0000000102838010 - address to symbolicate:当前方法的内存地址。
所以,上图为例:
1 2 |
$ cd CrashDemo/dSYMs $ atos -arch arm64 -o CrashDemo.app.dSYM/Contents/Resources/DWARF/CrashDemo -l 0x0000000102838010 0x0000000102838119 |
这时命令就会输出已经符号化过的信息: -[ViewController viewDidLoad] (in CrashDemo) (ViewController.m:45)
其中45就是问题代码在ViewController.m中的具体位置。
其实符号化的过程有多种方式,你可以参考Apple文档,对于其中UUID,只是为了我们找到App对应版本的dSYM文件,所以如果你能确定两者的对应,不需要我们再去获取。而且,使用上面方法,我们可以找到每一个版本对应的dSYM文件(假如你没有删除的话)。 
最后
愉快的改Bug吧
使用dSYM分析App崩溃日志的更多相关文章
- iOS系统app崩溃日志手动符号化
iOS系统app崩溃日志手动符号化步骤: 1.在桌面建立一个crash文件夹,将symbolicatecrash工具..crash文件..dSYM文件放到该文件夹中 a.如何查询symbolicate ...
- android app崩溃日志收集以及上传
源代码获取请到github:https://github.com/DrJia/AndroidLogCollector 已经做成sdk的形式,源代码已公开,源代码看不懂的请自行google. 假设想定制 ...
- 如何通过友盟分析发布后App崩溃日志-b
要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件包含了.DSYM文件. 我一般的做法是,发布成功后,把这个文件.xcarchive直接提交到代码版本库对应的版本分支里, ...
- 如何通过友盟分析发布后App崩溃日志
http://blog.csdn.net/totogo2010/article/details/39892467 要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件包含了 ...
- iOS Crash 分析 符号化崩溃日志
参考: http://blog.csdn.net/diyagoanyhacker/article/details/41247367 http://blog.csdn.net/diyagoanyhack ...
- iOS----- Crash 分析(文二)-崩溃日志组成
iOS Crash 分析(文二)-崩溃日志组成 现在我们看一个淘宝iOS主客崩溃的例子: ### 1.进程信息 ### Incident Identifier: E4201F10-6F5F-40F9- ...
- iOS----- Crash 分析(文三)- 符号化崩溃日志
未符号化的崩溃日志就象一本天书,看不懂,更别谈分析崩溃原因了.所以我们在分析日志之前,要把日志翻译成我们可以看得懂的文字.这一步我们称之为符号化. 在iOS Crash分析(文一)中已经提到过符号化的 ...
- 【转】iOS应用崩溃日志分析
作为一名应用开发者,你是否有过如下经历? 为确保你的应用正确无误,在将其提交到应用商店之前,你必定进行了大量的测试工作.它在你的设备上也运行得很好,但是,上了应用商店后,还是有用户抱怨会闪退 ! ...
- iOS:crash崩溃日志分析
一.前言: 作为一个合格的iOS开发者,除了具有规范强悍的编码能力外,还应该具有过硬的查错纠错能力.在项目运行时,程序崩溃是不可避免的,遇到这个问题,有时会出现一大堆的crash日志,艹,貌似看不懂呀 ...
随机推荐
- Centos7 ZooKeeper 安装过程
www.apache.org/dist/上可以下载Hadoop整个生态环境的组件,我下的Zookeeper3.4.6版本 我一般都是在一个虚拟机上将一.二步都做完,然后克隆出来,再到克隆出来的虚拟机上 ...
- VAssistX的VA Snippet Editor的类注释和函数注释
title:类注释shortcut:=== /******************************************************** [DateTime]:$YEAR$.$M ...
- 优化MyBatis配置文件中的配置
一.为实体类定义别名,简化sql映射xml文件中的引用 之前,我们在sql映射xml文件中的引用实体类时,需要写上实体类的全类名(包名+类名),如下: <!-- 创建用户(Create) --& ...
- 数据结构之Dijkstra算法
基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求 ...
- Java集合源码学习(三)LinkedList分析
前面学习了ArrayList的源码,数组是顺序存储结构,存储区间是连续的,占用内存严重,故空间复杂度很大.但数组的二分查找时间复杂度小,为O(1),数组的特点是寻址容易,插入和删除困难.今天学习另外的 ...
- 【131031】rel 属性 -- link标签中的rel属性,定义了文档与链接的关系
此属性通常出现在a,link标签中 属性值 Alternate -- 定义交替出现的链接 Alternate 属性值 -- alternate是LinkTypes的一个值,网页设计者可以通过此值,设计 ...
- SVN-简要说明
SVN官方推荐在一个版本库的根目录下先建立trunk.branches.tags这三个文件夹,其中trunk是开发主干,存放日常开发的内容:branches存放各分支的内容,比如为不同客户定制的不同版 ...
- PHP二维数组去除重复,重复值相加
$arr = array( array('id' => 122, 'name' => '张三', 'amount' => '1'), array('id' => 123, 'n ...
- linux SecureCRT ssh key认证登陆
转自:http://blog.chinaunix.net/uid-20639775-id-3207171.html 通过SecureCRT创建key登录认证 一.生成公钥/密钥对 使用SecureCR ...
- 模板模式与策略模式/template模式与strategy模式/行为型模式
模板模式 模版模式,又被称为模版方法模式,它可以将工作流程进行封装,并且对外提供了个性化的控制,但主流程外界不能修改,也就是说,模版方法模式中,将工作的主体架构规定好,具体类可以根据自己的需要,各自去 ...