美文网首页
iOS/OSX Crash的异常类型

iOS/OSX Crash的异常类型

作者: 凤舞玖天 | 来源:发表于2022-01-29 16:09 被阅读0次

我们在平时开发过程中经常会遇到的异常类型为Objective-C异常和UNIX信号。

1 Objective-C Exception

1.1 NSInvalidArgumentException

Name of an exception that occurs when you pass an invalid argument to a method, such as anilpointer where a non-nilobject is required.

传递非法参数给一个方法时抛出的异常。

常见场景:

NSNutableDictionaryr操作key或value的函数,如setObject:forKey:、removeObjectForKey等等。

NSMutableArray操作value的函数,如addObject:、 insertObject:atIndex:等等。

NSString操作函数,如initWithString:、initWithFormat:、stringWithString:等等。

这类异常一般都会在苹果官方文档中标出,对于不熟悉的接口,查看官方文档,基本上能够避免很多常见的NSInvalidArgumentException异常。

1.2 NSRangeException

Name of an exception that occurs when attempting to access outside the bounds of some data, such as beyond the end of a string.

尝试访问某些数据范围之外时抛出的异常。

常见场景:

NSArray包含索引的操作,如insertObject:atIndex:、objectAtIndex:等等。

NSString包含索引的操作,如characterAtIndex:、getCharacters:range:等等。

对于涉及到范围的接口,需对传入的索引、NSRange范围进行合法性检查,判断是否在集合数据范围内。

1.3 NSFileHandleOperationException

Raised byNSFileHandleif attempts to determine file-handle type fail or if attempts to read from a file or channel fail.

如果尝试确定文件句柄类型失败或尝试读取文件或通道失败,则会抛出此异常。

常见场景:

空间不足:会提示No space left on devie。

没有读写权限:会提示Bad file descriptor。

读文件失败。

在操作文件时,要验证文件句柄的有效性,对文件大小进行校验,对存储空间进行判断。

1.4 KVO引起的异常

常见场景【环境:Xcode12 IOS14】:

没有实现observeValueForKeyPath方法

抛出NSInternalInconsistencyException异常:

在VC pop时没有移除KVO监听

在IOS11及以上的系统不移除也不会崩溃。

多次移除KVO

抛出NSRangeException异常:

监听者和被监听者的生命周期不同

添加或移除时keyPath参数为nil

直接传递出错概率非常低,但传参路径复杂时容易出错

1.5 NSMallocException

iOS Crash之NSMallocException。

2 Mach异常和Unix信号(两者几乎是一一对应的:硬件产生的信号(通过CPU陷阱)被Mach层捕获【Mach异常】,BSD转换为Unix信号)

2.1 SIGSEGV (EXC_BAD_ACCESS)

一般是由于内存地址不合法导致SIGSEGV,例如访问未申请的虚拟内存地址,或者写入没有写的内存。子码可能有以下几种:

KERN_INVALID_FAILURE:试图访问未映射的内存导致的,包括访问数据和取指令。

KERN_PROTECTION_FAILURE:试图使用受保护的有效内存地址导致的,包括只读内存区域或不可执行内存区域。

SEGV_MAPERR:表示堆栈映射错误。

2.2 SIGBUS (EXC_BAD_ACCESS)

一般是由于地址未对齐导致的,例如内存地址对齐出错,或者试图执行没有权限的代码地址。子码有以下几种情况:

KERN_MEMORY_ERROR:试图访问当时无法返回数据的内存,如内存映射文件不可用。

EXC_ARM_DA_ALIGN:试图访问没有正确对齐的内存。此异常代码很少见,因为64位ARM CPU可处理未对齐的数据。但是,如果内存地址既未对齐又位于未映射的内存区域中,则可能会看到此异常子类型。

2.3 EXC_BAD_INSTRUCTION(SIGILL)

非法指令,通常与特定非法或未定义指令或操作数相关。

2.4 EXC_BREAKPOINT(SIGTRAP)

在ARM处理器上,断点异常类型指示跟踪陷阱中断进程。 跟踪陷阱使附上的调试器有机会在执行特定位置时中断该进程。

断点异常类型指示跟踪陷阱中断了该过程。 跟踪陷阱使附加的调试器有机会在执行的特定点中断该进程。 在ARM处理器上,它显示为EXC_BREAKPOINT(SIGTRAP)。 在x86_64处理器上,它显示为EXC_BAD_INSTRUCTION(SIGILL)。

Swift运行时将跟踪陷阱用于特定类型的不可恢复的错误-有关这些错误的信息,请参见Addressing Crashes from Swift Runtime Errors。 一些较低级别的库(例如Dispatch)会在遇到不可恢复的错误时使用此异常来捕获进程,并在崩溃报告的“其他诊断信息”部分中记录有关该错误的其他信息。 有关这些消息的信息,请参阅Diagnostic Messages。

当使用swift时,以下几种情况也会抛出此异常:

一个非可选类型值为nil;

强制类型转换失败;

如果要在自己的代码中使用相同的技术来解决不可恢复的错误,请调用__builtin_trap()函数。 这使系统可以生成带有线程回溯的崩溃报告,以显示你如何达到不可恢复的错误。

ILL_ILLTRP:ILL_ILLTRP at 0xxxxx通常是二进制出错,典型比如app升级前后二进制缓存出错。

2.5 EXC_ARITHMETIC(SIGFPE)

崩溃的线程执行了无效的算术运算。

包括除以0或取余0的情况,及发生数据溢出导致的除以0或取余0的情况;包括浮点错误。

The following values can be placed in si_code for a SIGFPE signal:

FPE_INTDIV Integer divide by zero.

FPE_INTOVF Integer overflow.

FPE_FLTDIV Floating-point divide by zero.

FPE_FLTOVF Floating-point overflow.

FPE_FLTUND Floating-point underflow.

FPE_FLTRES Floating-point inexact result.

FPE_FLTINV Floating-point invalid operation.

FPE_FLTSUB Subscript out of range.

2.6 SIGABRT

通常,发送此信号是因为进程调用了abort函数,例如,当应用遇到未捕获的Objective-C或C ++异常时。

2.7 SIGKILL

此信号表示系统中止进程,通常是调用函数exit()或kill(9)产生。

崩溃报告会包含代表中止原因的编码:

0x8badf00d:ate bad food,系统监视程序由中止无响应应用。注意在生命周期的不同阶段,触发看门狗机制的超时时间是不一样的。

0xc00010ff:cool off,系统由于过热保护中止应用,通常与特定的手机和环境有关。

0xdead10cc:dead lock,系统中止在挂起期间一直保持文件锁或SQLite数据库锁的应用。

0xbaadca11:bad all,系统由于应用在响应PushKit通知时无法报告CallKit呼叫而中止它。

0xbad22222:系统由于VoIP应用恢复太频繁而中止它。

0xc51bad01:watchOS终止了该应用程序,因为它在执行后台任务时占用了过多的CPU时间。

0xc51bad02:watchOS终止了该应用程序,因为它未能在分配的时间内完成后台任务。

0xc51bad03:watchOS终止了该应用程序,因为它未能在分配的时间内完成后台任务,但是系统总体上非常繁忙,以至于该应用程序可能没有收到太多的CPU时间来执行后台任务。

0xbada5e47:系统可能由于你启动了过多了后台任务而中止你的应用。

tips: SIGABRT和SIGKILL区别

两者都是发送给进程的中止信号。

SIGKILL等价于"kill -9",它是用来杀死僵尸进程;而SIGABRT等价于"kill -6",它是用来杀死正在运行的进程。

SIGKILL不能被捕获或忽略,接受进程也不能在收到此信号后做任何清理操作;而SIGABRT可以被捕获,但不能阻塞。

2.8 EXC_GUARD

受保护资源的非法访问,一般是由违背受保护资源防护触发,例如非法访问某些文件描述符。

2.9 EXC_RESOURCE

资源受限,应用由于达到资源的消耗限制而被退出,例如线程调度太频繁等。

3 C++异常

苹果开发同时支持OC和C++语法,其底层也基本上是由C++编写的,所以APP在IOS或OSX中运行时可能会抛C++异常。系统在捕获C++异常后的处理有两种情况:

1、如果此C++异常可以转换为OC异常,则抛给OC异常处理机制;

2、如果此C++异常不能转换为OC异常,则使用_cxa_rethrow()再次抛出;

相关文章

网友评论

      本文标题:iOS/OSX Crash的异常类型

      本文链接:https://www.haomeiwen.com/subject/ubgzhrtx.html