iOS 崩溃分析

1.工程设置

打包的时候生成dSYM(符号表),用来将崩溃的日志符号化

可以将release模式下设置为DWARF with dSYM File

注意:如需要在Xcode中进行错误日志分析,需要在上传到app store时勾选如下选项,上传符号表给Apple

image.png

2.dSYM文件收集

步骤如下:

在Xcode中顶部菜单Window -> Organizer -> Archives中,选中archive的版本右击,选择Show in Finder就可以获取dSYM文件了。

保存好你的app archive,app archive包含调试符号的dSYM。

如果app包含bitcode,需要使用Archives Organizer 中Download Debug Symbols 按钮来下载位码编译生成的dSYM。

3.收集错误日志

收集错误日志有如下几种途径:

a. Xcode,在Xcode中顶部菜单Window -> Organizer -> Crashes中,选择crash然后Show in Finder

b. 第三方,友盟、Bugly、神测等

c. 也可以将发生崩溃的设备连接Xcode,选择window-> devices -> 选择自己的手机 -> view device logs 就可以查看手机上所有的崩溃信息了。

d. 在Mac上使用控制台app查看设备或者模拟器的崩溃日志

e. 在崩溃设备上选择 设备-》隐私 -》 分析与改进 -》分析数据

4. 日志分析

.crash 文件包含:

a.顶部的设备型号、app名称、app版本号、启动时间、崩溃时间、操作系统版本等信息

image.png

b.含崩溃原因,这是操作系统发送用来杀死该进程的具体错误或特定信号

崩溃信号说明 https://developer.umeng.com/docs/193624/detail/204694

image.png

c.崩溃信息 Application Specific Infomation ,包含控制台信息,在模拟器上部分情况可用,在iOS设备上出于个人隐私原因通常会被隐藏

image.png

如果有未处理的异常,则它可能包含如下的异常回溯

d.崩溃线程堆栈,记录崩溃时所有的线程的回溯,其中一条被标记为崩溃的线程

e.崩溃线程的寄存器状态

f.加载到进程中的二进制数据镜像,这是app可执行文件和所有其它的库。Xcode使用它进行符号化,以查找符号文件和行号信息并且显示在堆栈跟踪中

如何查看崩溃日志

  1. 查看异常类型Exception Type,上面的异常类型为EXC_CRASH (SIGABRT)
    异常类型为EXC_BAD_INSTRUCTION (SIGKILL),SIGKILL信号指的是非法指令信号,意味着CPU正在尝试执行由于某种原因不存在或无效的指令,通常被用在当操作系统想要终止你的进程时。SIGKILL信号无法被处理,你的进程也无法捕获它
    异常类型为EXC_BAD_ACCESS(SIGSEGV),即段冲突信号,通常由内存错误引起的,要么时写入只读的内存,要么是尝试从内存中读取根本不存在的内容
  2. 查看异常回溯,查看崩溃时正在执行的代码

常见的内存错误:

image.png
  1. Objective-C 中objc_msgSend 或者retain/release
    这通常是由于你拥有某种类型的对象,然后该对象被释放并再次使用导致的。
  2. Unrecognized selector exception
    同一地址分配了一个新的对象取代了以前旧对象所在的位置,当代码尝试使用旧对象调用旧对象的函数,该地址处去有一个不同类型的不同对象,并且它根本无法识别该函数。

反汇编找出具体奔溃地址:

image.png
image.png

终端找出崩溃地址:

终端符号化崩溃日志

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

拷贝上面文件和崩溃日志文件、dSYM文件到统一目录,终端cd到这个目录执行如下命令:

./symbolicatecrash ./*.crash ./*.app.dSYM > symbol.crash

会生成一个symbol.crash文件,这个文件内容就是解析crash后所需要的内容。

PS: 若报错
Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash, 只需在终端中运行

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

若上面符号化没有变化,可以使用atos -o 还原某一行,命令如下:

atos -o (上文中.app.dSYM文件右键显示包内容,一直剥离到标有你工程名字的那一层,把那个文件的地址拖进来,这个文件的那一层已经是最后一层,不能再剥离了) -arch arm64 -l (crash日志里你想要解析的那一行从前面数第四列数字,复制过来,例如:0x1000a8000) (crash日志里你想要解析的那一行从前面数第三列数字,复制过来,例如:0x00000001009d80fc )回车就可以看到解析出来的这一行,完整示例

atos -o /Users/Chandler/Downloads/JDBClient.app.dSYM/Contents/Resources/DWARF/JDBClient -arch arm64 -l 0x1000a8000 0x00000001009d80fc 

多线程问题导致的错误

多线程错误通常时最难诊断和复现的错误类型之一,它们很难复现,因为只会偶尔导致崩溃,因此你的代码在99%的情况下正常工作,这些错误可能在很长一段时间内被忽略。

使用Thread Sanitizer可以调试处多线程问题导致的错误 ,Xcode -》 edit scheme → run -》 Diagnostics 选项卡勾选Thread Sanitizer (只能用于模拟器 )。

建议,创建队列时,可以在初始化提供自定义队列名称。

日志分析建议:

  1. 我们大部分时间都在看奔溃的特定代码和崩溃的线程上,重要的是要查看与崩溃相关的其他代码
  2. 查看崩溃线程以外的堆栈跟踪
  3. 查看多个崩溃日志,以找出特定的崩溃原因
  4. 使用Address Sanitizer 和Zombies等工具复现崩溃

5. 崩溃日志分析工具

  1. Xcode,在Xcode中顶部菜单`Window -> Organizer -> Crashes,如果上传了dSYM给Apple,可以直接在这里查看相关错误信息,但是信息没有第三方的统计的多。

注意:

  • 苹果自带的崩溃统计工具并不推荐用,如果想要使用这个功能,需要用户在iPhone中进行设置设置 -> 隐私 -> 诊断与用量 -> 诊断与用量数据(iOS8以下在通用中设置)选择自动发送,并与开发者共享。

然而很多人并不想和开发者共享数据,或者不设置这个选项,那这样就收集不到这部分的崩溃。

  • 静态库或者动态库Xcode不能查看崩溃的相关堆栈信息
  1. (推荐)第三方,友盟、Bugly、神测等,需要将上面每次发布版本的dSYM文件上传到第三方平台,第三方平台自动符号化错误日志,第三方平台还有行为日志可以追踪用户的操作的页面。

友盟2020年更新了SDK,将统计和崩溃两个功能分开了,最新的需要集成友盟的APMSDK。

如若需要还可以使用uid等其他信息精准定位错误原因 https://apm.umeng.com/platform/5b73d44bb27b0a02e20001c6/error_analysis/scrutiny,需要接入账号集成

  1. 使用 symbolicatecrash 工具
  2. 使用 atos -o

6.崩溃发生原因

代码问题:

  1. swift中可选值强制解包
  2. 数组越界
  3. 溢出,整形变量太大
  4. 未捕获的异常
  5. 自己代码写的断言

环境导致的崩溃,操作系统从外部杀死你的进程:

  1. 你的应用程序执行某件事时间太长
  2. 设备过热,操作系统将终止使用过多CPU的进程
  3. 设备内存不足,操作系统将终止正在使用大量内存的进程
  4. 无效的代码签名,操作系统强制对代码进行签名,如果签名无效或者代码未签名,操作系统将终止该进制并生成特定类型的崩溃日志

由操作系统终止的崩溃可以在设备日志和macOS控制台上找到,它们并不总是会出现在Xcode Organizer中

7. 崩溃防范

  1. 字典

    @{@"part_name":@"学院页",

    @"course_id":model.videoID?:@""}

    可变字段插入值判断nil

  2. 数组
    数组访问、修改和替换时需要做数组长度判断
    插入数组时需要判断nil

  3. 字符串访问、修改和替换时需要做字符串长度判断

  4. 其他地方的变量都建议加上nil值的判断

  5. 接口返回的数据都应是不可信的,应先判断数据类型是否正确,然后再判断是否有此值,再去取值

  6. 谨慎使用kvc

注意!!!

打包上传app store时一定要设置生成dSYM,并且保存好dSYM文件

参考资料:
https://segmentfault.com/a/1190000019569184
https://developer.apple.com/videos/play/wwdc2018/414/

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 崩溃日志的获取 崩溃日志的获取:ios设备上的应用闪退之后会生成崩溃报告存储在设备上,可以通过这样几种途径获取设备...
    纵横而乐阅读 5,531评论 0 1
  • 崩溃日志 如何得到crash report 当一个iOS应用程序崩溃时, 系统会创建一份crash日志保存在设备上...
    々莫等闲々阅读 7,988评论 0 2
  • 作为一名应用开发者,你是否有过如下经历?经常被领导叫去,让看哪位哪位客户运行APP又崩溃了,感觉解决;天天被产品狗...
    继续向前冲阅读 7,913评论 0 9
  • 一、获取 Crash、dSYM 文件 获取到的 .ips 改后缀为 .crash 即可 真机 Crash 文件目录...
    midmirror阅读 13,261评论 0 31
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 11,292评论 0 4