iOS之crash分析篇--捕获signal类型的崩溃信息

简介

上一篇文章我们讲述了,被系统自带的错误处理捕获的崩溃,可以通过UncaughtExceptionHandler机制捕获崩溃信息,我们要做的就是用自定义函数代替该ExceptionHandler即可。

另一种是未被捕获的异常,导致程序向自身发送了SIGABRT信号而崩溃。如果要处理它,我们还要利用unix标准的signal机制,注册SIGABRT,SIGBUS,SIGSEGV等信号发生时的处理函数。该函数中我们可以输出栈信息,版本信息等其他一切我们所想要的。这篇文章,我们将分析如何收集此类异常。

信号说明

  1. SIGHUP:用户终端退出进程时,终端将接收到SIGHUP信号。这个信号的默认操作为终止进程。
  2. SIGINT:程序终止信号(interrupt),在用户键入INTR字符(通常Ctrl-C)时发出,用于通知前台进程组终止进程。
  3. SIGQUIT:和SIGINT类似,但进程收到SIGQUIT会产生core文件,这个意义上类似于一个进程错误信号。
  4. SIGILL:执行了非法指令,通常因为可执行文件本身出席错误,或者试图执行数据段,堆栈溢出时也有可能产生这个信号。
  5. SIGATRAP:由断点指令或其他trap指令产生,由debugger使用。
  6. SIGABRT:调用abort函数生成的信号。
  7. SIGBUS:非法地址,包括内存地址对齐出错。比如访问一个四个字长的整数,但其地址不是4的倍数。
  8. SIGFPE:在发生致命的算术运算错误时发出,不仅包括浮点运算错误,还包括溢出及除数为0等其他所有的算术错误。
  9. SIGKILL:用来立即结束程序的运行,本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可以尝试发送这个信号。
  10. SIGUSR1、SIGUSR2:留给用户使用。
  11. SIGSEGV:试图访问未分配给自己的内存,或试图往没有权限的内存地址写数据。
  12. SIGSTOP:停止(stopped)进程的执行,但该信号可以被处理和忽略,用户键入SUSP字符时(通常Ctrl-Z)发出这个信号。

自定义SignalExceptionHandler

自定义一个customSignalExceptionHandler类,在.h文件中定义一个类方法:

cke_3673.png

在.m文件中实现:

cke_3674.png

这样我们就实现好了一个自定义SignalExceptionHandler类,并将signal异常崩溃堆栈保存成本地文件。

验证

这里最关键的一步,SignalHandler不要在debug环境下测试。因为系统的debug会优先去拦截。我们要运行一次后,关闭debug状态,直接在模拟器上点击我们build上去的app运行,而caughtExceptionHandler可以在调试状态下捕捉。完成这一系列操作后,在沙盒里可以查看到保存的SignalException.txt文件。以此追溯程序崩溃前的函数调用堆栈,进行准确debug。

cke_3675.png

总结

iOS的crash捕获分两种情况,有OC类异常和Signal信号捕获。

OC类异常,可以先通过NSGetUncaughtExceptionHandler保存先前注册的异常处理器,然后通过NSSetUncaughtExceptionHandler设置我们自己的异常处理器。处理结束后,需要在设置会原来的异常处理器。在我们自己的customUncaughtExceptionHandler里,需要手动调用下原来的处理器。

Signal信号捕获,Signal信号是由iOS底层mach信号异常转换后,以signal信号抛出的异常。既然是兼容posix标准的异常,我们可以用sigaction函数注册对应的信号。

这里,我们就知道了在iOS里如何使用代码进行crash的捕获。

因为xcode支持崩溃日志自动符号化,前提是本地有当时build/archive生成的dsym文件。我们在xcode上运行,崩溃日志已经自动符号化了。但如果dsym文件丢失或者拿到的崩溃日志不是标准的crash log,如何定位crash呢。

在后面的系列篇章中我会详细介绍符号化的过程,敬请期待!

欲了解更多详情,请参见:
华为官网:
https://developer.huawei.com/consumer/cn/forum/topic/0203721046139040273?fid=0101271690375130218?ha_source=zzh

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/4478396/blog/5547595