Understanding the Exception Types in a Crash Report:https://developer.apple.com/documentation/xcode/understanding-the-exception-types-in-a-crash-report
Crash类型与捕获
iOS端的crash分为两类,一类是NSException异常,另外一类是Signal信号异常。
NSException
NSException异常是ObjC代码导致的crash。
可以通过`NSGetUncaughtExceptionHandler`方法来hook错误信息。ObjC在objc_init中的`exception_init`函数中默认捕获了NSException,因此在Debug调试时能看到输出crash的描述信息。
Signal
Signal信号是由iOS底层mach信号异常转换后以signal信号抛出的posix标准异常。
在signal.h文件中可以看到31种signal异常的定义。可以通过signal函数捕获signal异常。
Crash分析SDK的实现原理
1. 捕获NSException与Signal异常,在回调中记录异常信息,并通过backtrace_symbols获取当前堆栈信息。
2. 将异常相关数据存储在本地,通过时间戳(或uuid)和设备信息等标识,同一时间一台设备不会出现两次crash。
3. 将异常信息上报给服务器,当服务器返回成功时,将本地磁盘缓存的这条记录清除。
4. 通过runloop阻塞住crash的立即执行(可选择)。
5. 程序在下次启动后,上报本地缓存的crash记录,服务器判断若为相同记录,则覆盖或不处理。
避免Crash的容错处理
容错处理一般使用runtime的方法交换和方法签名来实现。对于一些数组越界,参数为nil等问题通过交换方法类实现容错;对于调用的方法不存在的问题,通过交换NSObject的方法签名来实现容错。
需要注意的是,容错只是crash不会发生,但是代码还是存在问题的。而且因为没有crash,检测crash的sdk也不会发现这个bug。因此,容错问题发生时,也需要记录错误的调用堆栈等信息并上报服务器。
AvoidCrash:https://github.com/chenfanfang/AvoidCrash
Crash分析
符号表
符号表是内存地址与函数名,文件名,行号的映射表。可以在设置中开启符号表文件(.dSYM)的生成。
符号表主要用于当出现crash时,可根据crash日志文件记录的crash时函数堆栈地址,找到对应的方法名,从而方便找到crash产生的原因。可通过dwarfdump得到可执行程序和dSYM的uuid,若两者与crash日志文件的uuid文件相同,则代表是App的同一个版本,拥有相同的函数地址结构。
crash日志文件查看方式:
1. 集成的crashlytics,bugly,KSCrash等工具
2. Organizer的crashes
3. crash设备的device log
4. 控制台的崩溃报告
可以使用MachOView查看到偏移地址与符号名的对应关系。










网友评论