前言
在iOS开发过程中,总会遇到各种各样的崩溃问题,那么如何可能的降低应用的崩溃率,就成为每位iOS开发人员的必修课。所以,归纳总结iOS崩溃问题就显得尤为重要了。
crash类型
1 OC层面的crash
- 找不到方法的实现unrecognized selector
- KVC崩溃
- KVO崩溃
- NSInvalidArgumentException: 非法参数异常,传入非法参数导致异常,nil参数比较常见
- NSRangeException: 下标越界导致的异常
- NSGenericException: foreach的循环当中修改元素导致的异常
2 Signal层面的crash
除了OC层面的异常捕获之外,还有很多崩溃则需要利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。该函数中我们可以输出栈信息,版本信息等其他一切我们所想要的。这个unix标准的signal又是如何产生的呢?主要来源于这两类:
- 软件异常:软件异常主要来自 kill(),pthread_kill()。iOS 中的 NSException 未捕获,abort都属于这种情况。
- 硬件异常:硬件的信号始于处理器 trap,是和平台相关的。野指针崩溃大部分是硬件异常。
其中,硬件异常的流程是:硬件异常 -> Mach异常 -> Unix信号。根据《Mac OS X Internals》中说到的bsd相关的处理代码 ux_exception.c ,可以看到 Mach 异常和 Unix 信号存在的对应关系。
2.1 Mach 异常
- EXC_BAD_ACCESS: 不能访问的内存
- EXC_BAD_INSTRUCTION: 非法或未定义的指令或操作数
- EXC_ARITHMETIC: 算术异常(例如除以0)。iOS 默认是不启用的,所以我们一般不会遇到
- EXC_EMULATION: 执行打算用于支持仿真的指令
- EXC_SOFTWARE:软件生成的异常,我们在 Crash 日志中一般不会看到这个类型