一、崩溃类型
- 应用层存在bug ,即OC程序崩溃
如 数组越界,selector方法没实现等抛出一系列NSException
可通过系统API 注册UncaughtNSException处理函数捕捉,定位比较容易- 违反系统规则而出错
如 watchdog超时,访问了不属于本进程的内存地址,用户强制退出,低内存终止等,系统抛出unix信号,但没有错误堆站信息
可通过注册信号处理函数捕捉,但只能补拙有限的几种类型,定位较困难
二、Crash日志,几个重要的关键词
1、 进程信息
第一部分是闪退进程的相关信息:
- Incident Identifier : 是崩溃报告的唯一标识符。
- CrashReporter Key: 是与设备标识相对应的唯一键值。同一个设备上同一版本的App发生Crash时,该值都是一样的。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上。
- Hardware Model :标识设备类型。 如果很多崩溃日志都是来自相同的设备类型,说明应用只在某特定类型的设备上有问题。上面的日志里,崩溃日志产生的设备是iPhone 4s。
- Process:代表Crash的进程名称,通常都是我们的App的名字, []里面是当时进程的ID
- Path:崩溃文件的路径
- Identifier:项目标识符,就是Bundle Id
- Version:版本号
- Code Type:当前App的CPU架构
- Parent Process:当前进程的父进程,由于iOS中App通常都是单进程的,一般父进程都是launchd
2、基本信息
这部分给出了一些基本信息
- Date/Time:闪退发生的日期
- Launch Time:进入应用的时间
- OS Version:设备的iOS版本
- Report Version-Crash:日志的格式,目前基本上都是104,不同的version里面包含的字段可能有不同
3、异常信息
- Exception Type:异常的类型。
- Exception Codes :异常错误码
- Termination Reason:闪退的原因,比如常见的数组越界啊,什么的。
- Triggered by Thread:出现问题在哪个线程,这个比较重要,首先确定在哪个线程中出了问题,然后再去定位。
4、线程回溯
这部分提供应用中所有线程的回溯日志。
回溯是闪退发生时所有活动帧清单。它包含闪退发生时调用函数的清单. 线程调用的一些堆栈信息,压根看不懂,所有需要进行符号化处理。看下面这行日志:
05 UIKit 0x00000001943bd7fc 0x194343000 + 501756
它包括四列:
帧编号—— 此处是12。
二进制库的名称 ——此处是 UIKit
调用方法的地址 ——此处是 0x00000001943bd7fc
第四列分为两个子列,一个基本地址和一个偏移量。此处是0x194343000 + 501756, 第一个数字指向文件,第二个数字指向文件中的代码行。
5、 二进制映像(Binary Images)
这部分列出了当Crash发生时被装载进进程内存空间的依赖库或者模块
三、异常类型信息
1、Exception Type
1)EXC_BAD_ACCESS
此类型的Excpetion是我们最长碰到的Crash,通常用于访问了不改访问的内存导致。一般EXC_BAD_ACCESS后面的"()"还会带有补充信息。
- SIGSEGV: 通常由于重复释放对象导致,这种类型在切换了ARC以后应该已经很少见到了。
- SIGABRT: 收到Abort信号退出,SIGABRT 异常是由于某个对象接收到未实现的消息引起的。
SEGV:(Segmentation Violation),代表无效内存地址,比如空指针,未初始化指针,栈溢出等;
- SIGBUS:总线错误,与 SIGSEGV 不同的是,SIGSEGV 访问的是无效地址,而 SIGBUS 访问的是有效地址,但总线访问异常(如地址对齐问题)
- SIGILL:尝试执行非法的指令,可能不被识别或者没有权限
2)EXC_BAD_INSTRUCTION
此类异常通常由于线程执行非法指令导致
3)EXC_ARITHMETIC
除零错误会抛出此类异常
2、Exception Code 异常编码
前面日至的第3部分找到异常编码。有些编码比较常见。通常,异常编码以一些文字开头,紧接着是一个或多个十六进制值,此数值正是说明闪退根本性质的所在。 从这些编码中,可以区分出闪退是因为程序错误、非法内存访问或者是其他原因
常见的异常编码:
- 0xbaaaaaad 此种类型的log意味着该Crash log并非一个真正的Crash,它仅仅只是包含了整个系统某一时刻的运行状态。通常可以通过同时按Home键和音量键,可能由于用户不小心触发
- 0xbad22222 当VOIP(指在 IP 网络上使用 IP 协议以数据包的方式传输语音)程序在后台太过频繁的激活时,系统可能会终止此类程序
- 0x8badf00d 程序启动或者恢复时间过长被watch dog终止,通常是应用花费太多时间而无法启动、终止或响应用系统事件
- 0xc00010ff 程序执行大量耗费CPU和GPU的运算,导致设备过热,触发系统过热保护被系统终止
- 0xdead10cc 程序退到后台时还占用系统资源,如通讯录被系统终止
- 0xdeadfa11 程序无响应,用户强制关闭
(注意: 在后台任务列表中关闭已挂起的应用不会产生崩溃日志。 一旦应用被挂起,它何时被终止都是合理的。所以不会产生崩溃日志。)
四、低内存崩溃
低内存崩溃日志与其他类型的崩溃日志很不一样,它们不指向特定的文件和代码行。相反,它们画出了闪退时设备上的内存使用情况的图表
头部还是跟其他崩溃日志很像的: 提供了 Incident Identifier, CrashReporter Key, Hardware Model, OS Version等信息。
接下来部分是低内存崩溃日志特有的:
- Free pages 指可用内存页数。每页大小约是4KB, 上面的日志中,可用内存约为3,872 KB (或者说 3.9 MB)。
- Purgeable pages 是那部分可被清除或重用的内存。在上面的日志中,是0KB。
- Largest process是闪退时使用大部分内存的应用名称,在上面的日志中,正是你的应用!
- Processes显示了闪退时各进程列表,还包含内存使用量。包含进程名 (第一列), 进程唯一标识符(第二名), 进程使用的内存页数(第三列)。最后一列是每个应用的状态。通常,发生闪退的应用的状态是 frontmost。