iOS Crash 捕获

iOS Crash 捕获(个人简单理解)

iOS的Crash捕获有两种: 信号量异常 系统的异常捕获
信号量异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//信号量异常 通过signalHandler来捕获系统发过来的异常信号,然后暂停所有线程,去获取堆栈信息
void InstallSignalHandler(void)
{
    signal(SIGHUP, SignalExceptionHandler);
    signal(SIGINT, SignalExceptionHandler);
    signal(SIGQUIT, SignalExceptionHandler);
    signal(SIGABRT, SignalExceptionHandler);
    signal(SIGILL, SignalExceptionHandler);
    signal(SIGSEGV, SignalExceptionHandler);
    signal(SIGFPE, SignalExceptionHandler);
    signal(SIGBUS, SignalExceptionHandler);
    signal(SIGPIPE, SignalExceptionHandler);
}

//获取异常的堆栈信息
通过task_threads来获取当前所有的线程
//暂停线程
thread_suspend
//获取线程的各种信息以及调用堆栈(内存地址))
thread_get_state
//根据上一步的堆栈地址找到对应的符号表名字
dladdr
//然后获取到所有加载的动态库
_dyld_image_count //动态库的数量
_dyld_get_image_name //根据index得到动态库的名称
_dyld_get_image_vmaddr_slide //根据index得到动态库的偏移地址

//然后使用dladdr的名称跟_dyld_get_image_name做对比,如果一致,则可以使用thread_get_state获取到的地址减去_dyld_get_image_vmaddr_slide获取到的偏移地址,然后就是符号地址了
//然后就可以用符号地址从dsym中查询到我们的崩溃信息

//恢复线程
thread_resume

//杀死app
abort()

系统的异常捕获

直接通过NSSetUncaughtExceptionHandler就可以获取到NSException信息,通过NSException的属性来获取到堆栈信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void HandleException(NSException *exception)
{
    // 异常的堆栈信息
    NSArray *stackArray = [exception callStackSymbols];
    // 出现异常的原因
    NSString *reason = [exception reason];
    // 异常名称
    NSString *name = [exception name];
    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];
    NSLog(@"%@", exceptionInfo);
    [UncaughtExceptionHandler saveCreash:exceptionInfo];
}

void InstallUncaughtExceptionHandler(void)
{
    NSSetUncaughtExceptionHandler(&HandleException);
}

//别忘了,crash传递,方便其他sdk也能收集到crash信息
//如果同时有多方通过NSSetUncaughtExceptionHandler注册异常处理程序,和平的作法是:后注册者通过NSGetUncaughtExceptionHandler将先前别人注册的handler取出并备份,在自己handler处理完后自觉把别人的handler注册回去,规规矩矩的传递

crash 传递

系统的异常捕获:如果同时有多方通过NSSetUncaughtExceptionHandler注册异常处理程序,和平的作法是:后注册者通过NSGetUncaughtExceptionHandler将先前别人注册的handler取出并备份,在自己handler处理完后自觉把别人的handler注册回去,规规矩矩的传递 信号:同样的,也是通过sigaction先保存原来的处理方式,然后我们处理完后,再对其进行处理

参考资料:

  1. iOS 异常捕获
  2. dladdr - 获取某个地址的符号信息
  3. iOS 性能监控方案 Wedjat(上篇)
  4. iOS 之 Thread调用栈学习
  5. 获取任意线程调用栈的那些事
  6. Mach-O文件介绍之ASLR(进程地址空间布局随机化)
  7. [漫谈iOS Crash收集框架 程序媛念茜 — 单线程妞](https://nianxi.net/ios/ios-crash-reporter.html)
  8. Linux 进程学习(四)—— sigaction 函数
  9. Understanding and Analyzing Application Crash Reports

--EOF--

若无特别说明,本站文章均为原创,转载请保留链接,谢谢