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先保存原来的处理方式,然后我们处理完后,再对其进行处理
参考资料:
- iOS 异常捕获
- dladdr - 获取某个地址的符号信息
- iOS 性能监控方案 Wedjat(上篇)
- iOS 之 Thread调用栈学习
- 获取任意线程调用栈的那些事
- Mach-O文件介绍之ASLR(进程地址空间布局随机化)
-
[漫谈iOS Crash收集框架 程序媛念茜 — 单线程妞](https://nianxi.net/ios/ios-crash-reporter.html) - Linux 进程学习(四)—— sigaction 函数
- Understanding and Analyzing Application Crash Reports
--EOF--
若无特别说明,本站文章均为原创,转载请保留链接,谢谢