捕捉异常代码来自KSCrash!
针对不同的异常(Objective-C异常、Mach异常、UNIX信号、C++异常)需要不同的捕捉方式。
1 Objective-C 异常
苹果提供了两个函数来设置顶层OC异常处理句柄,可以使你在程序终止之前记录最新的日志。获取当前已设置的顶层异常处理句柄
NSUncaughtExceptionHandler * NSGetUncaughtExceptionHandler(void);设置顶层异常处理句柄
void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *);
异常处理函数:
typedef void (NSException * _Nonnull) NSUncaughtExceptionHandler;
OC异常处理步骤:
1、调用NSGetUncaughtExceptionHandler获取当前顶层异常处理句柄,以供在异常发生时调用,防止异常处理链断裂。
2、调用NSSetUncaughtExceptionHandler设置自己的顶层异常处理句柄,以在发生异常时可以获取最新的异常日志。
3、在异常处理函数中,收集异常信息。特别地,异常发生时系统会提供NSException信息,我们可以从中得到OC异常的详细信息:
4、调用NSGetUncaughtExceptionHandler取得的上一次异常处理函数。
static void handleException(NSException* exception, BOOL currentSnapshotUserReported) {
// 收集异常信息
...
if (g_previousUncaughtExceptionHandler != NULL)
{
g_previousUncaughtExceptionHandler(exception);
}
}
...
g_previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
NSSetUncaughtExceptionHandler(&handleUncaughtException);
...
2 Mach 异常
Mach异常是内核级异常,在系统的位置如下图所示:OS X kernel architecture
2.1 Mach相关知识
Mach在系统中处于最接近底层的模块,是XNU内核的内核,被BSD包裹。Mach内核作为系统一个底层的基础,仅与驱动操作系统所需的最低需要有关。 其他所有内容都由操作系统的更高层来实现,然后再利用Mach并以其认为合适的任何方式对其进行操作。
Mach提供了一小部分内核抽象,这些内核抽象被设计为既简单又强大。与Mach异常相关的内核抽象有:tasks
资源所有权单位; 每个任务由一个虚拟地址空间、一个端口权限名称空间和一个或多个线程组成。 (类似于进程)threads
任务中CPU执行的单位。ports
安全的单工通信通道,只能通过发送和接收功能(称为端口权限)进行访问。
这些内核对象,对于Mach来说都是一个个的Object,这些Objects基于Mach实现自己的功能,并通过Mach Message来进行通信,Mach提供了相关的应用层的API来操作。与Mach异常相关的几个API有:task_get_exception_ports:获取task的异常端口
task_set_exception_ports:设置task的异常端口
mach_port_allocate:创建调用者指定的端口权限类型
mach_port_insert_right