OC类异常
NSException是OC中的异常类,定义自己的拦截函数并在启动时设置就可以捕获异常。
常见的OC异常
具体问题具体分析
异常名称 | 含义 |
---|---|
NSInvalidArgumentException | 传递了非法的参数 |
NSRangeException | 当你访问了数组等对象的不存在的索引时 |
NSGenericException | 经常出现在遍历数组时增删元素 |
NSInternalInconsistencyException | 不一致导致出现的异常,不可变当成可变的 |
NSFileHandleOperationException | 处理文件时的一些异常 |
NSMallocException | 内存不足 |
捕获方式
多个ExceptionHandler冲突
当多个crash收集框架同时存在时,就会存在冲突,处理不当会导致其他handler接收不到异常。我们应该先判断是否有前者已经注册了handler,如果有则应该把这个handler保存下来,在自己处理完自己的handler之后,再把这个歌handler抛出去,供前面的注册者处理。
Mach异常
内核级别的异常,不可直接观察到,它们往往最终转换为Signal信号,从而被我们检测到,以下截取一段KSCrash内对Mach和Signal对应映射的一段代码。
常见的Mach异常类型
异常名称 | 含义 |
---|---|
EXC_BAD_ACCESS | 臭名昭著的野指针,尝试访问已经释放的内存或向已释放的对象发消息就会出现。这个崩溃发生时,查看崩溃日志,却往往得不到有用的栈信息。还好,有一个方法用来解决这个问题:NSZombieEnabled。在Xcode中Edit Scheme可以开启Zombie Objects,这样以来发送给未知内存的消息会转发给僵尸对象,然后跳入调试器,这样你就可以查看到底哪时出了问题。 |
EXC_BAD_INSTRUCTION | 运行了非法的指令,往往是运行指令的参数不对(0或者nil的参数) |
EXC_RESOURCE | 程序资源上限(cpu占用过高或者内存不足) |
EXC_GUARD | 一些C函数访问错误导致的异常。 |
EXC_ARITHETIC | 除0 |
watchdog | 固定的错误码:0x8badf00d 。在iOS上,它经常出现在执行一个同步网络调用而阻塞主线程的情况。因此,永远不要进行同步网络调用。 |
Signal异常
Signal信号是由iOS底层mach信号异常转换后,以signal信号抛出的异常。
常见的Signal类型
信号名称 | 含义 |
---|---|
SIGSEGV | 段错误信息。当硬件出现错误、访问不可读的内存地址或向受保护的内存地址写入数据时,就会发生这个错误。 |
SIGILL | 当在处理器上执行非法指令时,它就会发生。执行非法指令是指,将函数指针会给另外一个函数时,该函数指针由于某种原因是坏的,指向了一段已经释放的内存或是一个数据段。有时你收到的是EXC_BAD_INSTRUCTION而不是SIGILL,虽然它们是一回事,不过EXC_*等同于此信号不依赖体系结构。 |
SIGKILL | 立即结束程序的运行的信号。和其他信号不同,SIGKILL 是不可被捕获的。这是 Linux / Mach 内核的限制,这种限制就是为了让操作系统在程序无法响应的时候,可以从上一层控制进程的生命周期。(系统的MetricKit可以捕获) |
SIGABRT | 调用abort函数生成的信号,当SIGABRT出现时,控制台通常会输出大量的信息,说明具体哪里出错了。由于它是可控制的崩溃,所以可以在LLDB控制台上键入bt命令打印出回溯信息。 |
SIGTRAP | 陷阱信号。它并不是一个真正的崩溃信号。它会在处理器执行trap指令发送。LLDB调试器通常会处理此信号,并在指定的断点处停止运行。如果你收到了原因不明的SIGTRAP,先清除上次的输出,然后重新进行构建通常能解决这个问题。 |
SIGBUS | 总线错误信号。代表无效内存访问,即访问的内存是一个无效的内存地址。 |
SIGPIPE | 管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。 |
SIGHUP | 用户终端退出进程时,终端将接收到SIGHUP信号。这个信号的默认操作为终止进程。 |
SIGFPE | 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误。 |