Crash 日志 简单分析 缩小查找范围

看懂 Crash 日志

Crash 头部信息

  • Incident Identifier:每个 Crash 生成的唯一的 uuid.

  • CrashReporter Key:CrashReporter 的 uuid, 如果自己捕获日志,这个可以忽略。

  • Hardware Model:机型

  • Process:进程名和进程ID

  • Path:进程的可执行文件路径

  • Identifier:Info.plist 中配置的 CFBundleIdentifier 值

  • Version: CFBundleVersion (CFBundleVersionShort) 即应用的Build号+版本号

  • Code Type:机型的 CPU 架构,但是不是详细的架构名。比如 arm64e 在这里也是 ARM-64

  • Parent Process:父进程和进程ID

  • Data/Time: Crash发生的具体时间。

  • Launch Time: 进程启动时间

  • OS Version: iOS 系统版本和 build号

  • Report Version: Crash日志格式的版本号,一般是 104。如果这个version偏高,用系统的symbolicatecrash命令不能符号化日志,一般如果看到是204, 改成104之后用symbolicatecrash就可以符号化了

Crash 异常码

在 Crash 头部信息之下, 会有个段记录了 Crash 异常码。类似下图:


这里我们应该关注:

  • Exception Type:异常码,一般格式是 Mach异常码 ( UNIX 信号类型 )

  • Exception Subtype:一般情况里面带的是 Mach异常的 subcode, 还有 Crash 相关地址信息。

  • Triggered by Thread:发生Crash的线程,大部分情况到这个线程的堆栈里面去看 Crash 堆栈。

  • Application Specific Information:如果是 Objc/c++ Exception 异常,这里是异常的信息,这个是定位异常的关键信息

  • Last Exception Backtrace:抛出异常的代码堆栈, 如果是 Objc/c++ Exception 异常造成的 Crash,就看这个堆栈,Crashed Thread: 里的堆栈是 abort(),没有意义。

附异常码的解释, 非所有异常码,只是我们 Crash 中可能会看到的 :

Mach 异常 简介 使用场景
EXC_BAD_ACCESS (SIGBUS) 总线错误 1、内存地址对齐出错 2、试图执行没有执行权限的代码地址
SIGSEGV 段错误 1、访问未申请的虚拟内存地址 2、没有写权限的内存写入
EXC_BAD_INSTRUCTION (SIGILL) 非法指令,即机器码指令不正确 1, iOS 上偶现的问题,遇到之后用户会连续闪退,直到应用二进制的缓存重新加载 或重启手机。此问题挺影响体验,但是报给苹果不认,因为苹果那边没有收集到,目前没有太好办法。因为 iOS 应用内无法对一篇内存同时获取 w+x 权限的,因此应用无法造成此类问题,所以判断是苹果的问题。
EXC_ARITHMETIC (SIGFPE) 算术运算出错,比如除0错误 iOS 默认是不启用的,所以我们一般不会遇到。
EXC_SOFTWARE (我们在 Crash 日志中一般不会看到这个类型,苹果的日志里会是 EXC_CRASH) (SIGSYS) 系统调用异常
SIGPIPE 管道破裂 1, Socket通信是可能遇到,如读进程以及终止时,写进程继续写入数据。2, 根据苹果的文档,我们可以忽略这个信号https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/CommonPitfalls/CommonPitfalls.html
SIGABRT abort() 发生的信号 典型的软件信号,通过 pthread_kill() 发送
SIGKILL 进程内无法拦截 1, exit(), kill(9) 等函数调用 2, iOS系统杀进程用的,比如 watchDog 杀进程
EXC_BREAKPOINT SIGTRAP 由断点指令或其它trap指令产生 部分系统框架里面会用 __builtin_trap() 来产生一个 SIGTRAP 类型的 Crash
EXC_GUARD 文件句柄错误 试图 close 一个内核的 fd.
EXC_RESOURCE 资源受限 线程调度太频繁,子线程每秒被唤醒次数超过150:https://stackoverflow.com/questions/25848441/app-shutdown-with-exc-resource-wakeups-exception-on-ios-8-gm

Crash 堆栈

下面一张图介绍了 Crash 堆栈中每个段的含义(在网上找的说的挺细):


1346982-d01e701afe7cdd32.png

Signal信号的类型:

  • SIGABRT–程序中止命令中止信号
  • SIGALRM–程序超时信号
  • SIGFPE–程序浮点异常信号
  • SIGILL–程序非法指令信号
  • SIGHUP–程序终端中止信号
  • SIGINT–程序键盘中断信号
  • SIGKILL–程序结束接收中止信号
  • SIGTERM–程序kill中止信号
  • SIGSTOP–程序键盘中止信号
  • SIGSEGV–程序无效内存中止信号
  • SIGBUS–程序内存字节未对齐中止信号
  • SIGPIPE–程序Socket发送失败中止信号
    SIGABRT
    就crash而言,SIGABRT是一个比较好解决的,因为他是一个可掌控的crash。App会在一个目的地终止,因为系统意识到app做了一些他不能支持的事情。
    通常, SIGABRT 异常是由于某个对象接收到未实现的消息引起的。 或者,用简单的话说,在某个对象上调用了不存在的方法。
    SIGSEGV
    SIGSEGV程序无效内存中止信号,一般是表示内存不合法,
    SIGBUS
    SIGBUS程序内存字节未对齐中止信号,

补充常见的Exception Codes代码类型

Exception Codes: 常见代码有以下几种
0x8badf00d错误码:Watchdog超时,意为“ate bad food”。
0xdeadfa11错误码:用户强制退出,意为“dead fall”。
0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。
0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。
0xc00010ff错误码:因为太烫了被干掉,意为“cool off”。
0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为“dead lock”
异常代码0x8badf00d指示应用程序已终止的iOS 因为看门狗超时发生,应用程序时间太长、终止,或对系统时间作出相应。一个常见的原因是做在主线程上的同步联网。无论操作是线程0上,需要搬到后台线程,或处理方式不同,所以它不会阻止在主线程。

补充常见的Exception Type异常类型的信息:

1、EXC_BAD_ACCESS:此类型是最常见的crash, 通常用于访问了不该访问的内存导致的,一般EXC_BAD_ACCESS后面的()还会带有补充信息
野指针错误形式在Xcode中通常表现为:Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)错误。因为你访问了一块已经不属于你的内存。
2、SIGSEGV:通常由于重复释放对象导致, 一般在ARC以后很少见到
3、SIGABRT: 收到Abort信号退出, 通常Foundtion库中的容器为了保护状态正常会做一些检测, 例如插入nil到数据中等会遇到此类错误.
4、SEGV(Segmentation Violation):代表无效内存地址, 比如空指针, 未初始化指针, 栈溢出等.
5、SIGBUS:总栈错误, 与SIGSEGV不同的是, SIGSEGV访问的是无效的地址, 而SIGBUS访问的是有效的地址, 但是总栈访问异常(如地址对齐问题)
6、SIGILL: 尝试执行非法的指令, 可能不被识别或者没有权限
7、SIGFPE: 数学计算相关问题, 比如除零操作
8、SIGIPIPE: 管道另一端没有进程接手数据
9、EXC_BAD_INSTRUCTION:此类异常通常由于线程执行非法指令导致
10、EXC_ARITHMETIC:除零错误会抛出此类异常

Crash 分析方法

请查看网上文章比较详细:详细1 详细2

你可能感兴趣的:(Crash 日志 简单分析 缩小查找范围)