iOS Crash解析
iOS 开发过程中会遇到crash,有些很容易就能定位到,例如数组越界、类型不匹配、方法不存在等。但是有些就比较头疼了,莫名其妙的,崩溃的让你怀疑自己是不是写了假程序,就算查看日志也是一堆只有机器才能看懂的内存地址,无法定位。其实可以根据原始crash文件,再配合一些其他文件和Xcode自带的解析工具symbolicatecrash
,就可以是crash文件符号化,让你轻松定位到崩溃的元凶(当然说到底代码要是自己写的,那这个锅只能默默背着了。毕竟自己挖的坑,含着泪也要慢慢爬出来。😂)。
-
debug模式
debug模式一般就是真机联调或者直接使用模拟器跑代码,这样的情况下crash的时候控制台都会用日志打印的,如下:
debug模式下crash日志
当然这是最直接的方法,你也可以从手机里面导出crash文件,结合.dYSN等文件解析crash文件,或者利用第三方的网站去统计,具体的方法会在下面说到。
-
release模式
一般打包给测试人员或者app上架后出现crash就不好跟踪了,这样的情况也比debug模式麻烦多了,但是麻烦归麻烦,还是有解决办法的嘛!
1.首先可以使用Xcode自带的crash解析工具symbolicatecrash
解析之前需要三个素材:(xxx代表应用名)
(1)xxx.app.dSYM(其实是一个目录,在子目录中包含了一个16进制的保存函数地址映射信息的中转文件,所有Debug的symbols都在这个文件中(包括文件名、函数名、行号等),所以也称之为调试符号信息文件),找寻方法:
Xcode->Window->Organizer找到Archives->右击Show in Finder->右击.xcarchive文件->显示包内容在dSYMs文件夹中找到.app.dSYM
(2)xxx.app(一般这个文件是隐藏后缀名的),找寻方法:Xcode->Window->Organizer找到Archives->右击Show in Finder->右击.xcarchive文件->显示包内容在Products->Applications文件夹中找到xxx.app
,或者在修改ipa包后缀名为.zip,解压完后的Payload里面就是xxx.app文件(注意:ipa包必须是你出现crash设备安装的ipa包)
(3)xxx.crash(崩溃日志),如果出现崩溃的手机你可以拿到手的话,只需要把出现崩溃的设备连接到手机上,在Xcode->window->Devices->找到你的设备->View Devices Logs中找到crash,导出就好了。(还有一点就是如果打包的电脑跟你解析crash的电脑是同一个的话,那么这里导出的日志应该是解析好的,这是因为在打包的时候会建立 .app 及 .dYSM 两个文件的索引,所以可以自动解析 crash log 文件,要是没解析的话估计需要自己按照下面的方法解析了。)
但是对于那些从app store上下载的用户,出现崩溃的时候肯定没办法及时拿到crash文件,对于这些崩溃可以自己敲代码扑捉crash或者靠一些网站统计了,例如iTunes connect里面的app分析(交互不是很好,我没怎么用过)、国内的bugly(我用的比较多,具体使用和注意事项下面会说到)、bugTag、蒲公英、友盟等等,还有国外的Crashlytics、Flurry等。
以上三个素材找到后可以把他们放到桌面新建的Release-Crash文件夹中,最后还需要加入一个symbolicatecrash,它的路径可以在终端利用下面的命令找到(记得把Xcode路径换成自己的🤓),根据路径在前往文件夹中找到symbolicatecrash,拷贝到桌面Release-Crash文件夹中。
find /Applications/Xcode\ 8.1.app -name symbolicatecrash -type f
到此准备工作已经全部OK了,接下来就是解析了,cd
到Release-Crash文件夹,可以ls
下看里面内容对不对,先检查下xxx.app/xxx、xxx.app.dSYM以及xxx.crash的UUID是否一致,这是解析的前提,不一样的话,你就别解析了,基本不会成功的,获取UUID的命令如下:
dwarfdump --uuid xxx.app/xxx
dwarfdump --uuid xxx.app.dSYM
crash文件打开后Binary Images:后面第一个大长串就是crash文件的uuid
xxx.app.dSYM和xxx.app/xxx的UUID
crash文件的UUID
三个UUID一致的话就可以利用下面的命令解析:(./symbolicatecrash+.crash文件路径+.app.dSYM路径+>+Log.crash
这几个最好用空格分开,路径用全路径,解析的结果就是Log.crash)
./symbolicatecrash ....../xxx.crash ....../xxx.app.dSYM > Log.crash
在这个过程中常见的一个错误就是下面这个,
Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 69.
好像是环境变量的原因,解决也很简单,执行下面的命令就好了
export DEVELOPER_DIR="/Applications/Xcode\ 8.1.app/Contents/Developer"
至此解析结束,你可以在Release-Crash/Log.crash
里面看到符号化后的crash文件
2.第二种方法就是利用第三方crash统计网站
不管是debug还是release或是用户从app store上下载的用户,crash都可以统计到,你还可以上传.app.dSYM文件,让网站帮你符号化崩溃日志。我使用的是腾讯的bugly,我感觉bugly统计比较及时,而且界面还算友好,可以看到原始crash日志也可以看到解析完的crash日志,针对crash给出修改意见
想要看到解析完全的日志,必须要上传指定的.app.dSYM(这不是废话嘛!😂),uuid需要跟bugly指定的一致,不然传上去也没用,所以打包的时候做好.app.dSYM的备份是很重要的,
bugly
提供了使用脚本自动上传.app.dSYM的功能(传送门),亲测!是可以的没问题很及时。注意:有一个点,我遇到过解析的结果是这样的,直接是hidden了,.app.dSYM也是正确的(我发誓🤘保证是正确的),可试了几次都是这样的,后来找到解决办法了,是我打包的时候勾选上了
bitcode
,导致现在这样(具体原因也不知道为啥,估计要深度研究下啥叫bitcode
),取消勾选后就可以看解析结果了(但是不知道会不会挖一个坑啊!🤔)3.还可以使用代码自己扑捉crash
我觉得上面提到的第三方网站统计crash应该原理估计就是这样的(我猜的!😳猜错应该不会有人打我吧!),代码也很简单如下:
注册一个异常触发方法:NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 在触发方法中打印崩溃日志: void uncaughtExceptionHandler(NSException *exception) { NSLog(@"%@", [NSString stringWithFormat:@"MainThread Name: %@\n%@ \n %@", [NSThread mainThread].name, exception, exception.callStackSymbols]); }
你可以在触发的方法中把错误日志发送到个人邮箱或者上传到公司服务器上做统计。但是这也只是统计crash日志,解析这块还是需要上面的方法解析。
4.如果觉得命令行解析比较麻烦的话,有一位大神开发过一个解析工具,很轻松就可以解析了-->解析小工具说明
界面也很简单,需要上传打包时候的.xcarchive文件,加上需要解
析的内存地址和slide address(偏移地址),解析结果就出来了
相关文章:
1.Crash文件的解析(一)以及Crash的内容说明