文章目录
App崩溃问题
app经常会遇见崩溃问题,比如下
- 数据越界
- 多线程操作同一指针,当指针为空时崩溃
- 野指针问题
KVO
问题NSNotification
线程问题
以及不可捕获的崩溃问题:
- 后台任务超时
- App超过系统限制的内存大小被杀死
- 主线程卡顿被杀死
可捕获的崩溃信息收集
对于可以捕获的崩溃问题,我们可以通过崩溃日志分析,例如PLCrashReporter 和bugly
这些三方崩溃分析工具。
PLCrashReporter实现
在崩溃日志中,Exception信息头部经常有
Exception Type: EXC_CRASH (SIGABRT)
SIGABRT
就代表着一种崩溃信息,类似还有SIGSEGV
、SIGBUS
PLCrashReporter
通过注册这些崩溃signalHandler回调
就可以获得崩溃信息。
在 PLCrashReporter
源码中
/**
* Register a new signal @a callback for @a signo.
*
* @param signo The signal for which a signal handler should be registered. Note that multiple callbacks may be registered
* for a single signal, with chaining handled appropriately by the receiver. If multiple callbacks are registered, they may
* <em>optionally</em> forward the signal to the next callback (and the original signal handler, if any was registered) via PLCrashSignalHandlerForward.
* @param callback Callback to be issued upon receipt of a signal. The callback will execute on the crashed thread.
* @param context Context to be passed to the callback. May be NULL.
* @param outError A pointer to an NSError object variable. If an error occurs, this pointer will contain an error object indicating why
* the signal handlers could not be registered. If no error occurs, this parameter will be left unmodified. You may specify
* NULL for this parameter, and no error information will be provided.
*
* @warning Once registered, a callback may not be deregistered. This restriction may be removed in a future release.
* @warning Callers must ensure that the PLCrashSignalHandler instance is not released and deallocated while callbacks remain active; in
* a future release, this may result in the callbacks also being deregistered.
*/
- (BOOL) registerHandlerForSignal: (int) signo
callback: (PLCrashSignalHandlerCallbackFunc) callback
context: (void *) context
error: (NSError **) outError
{
/* Register the actual signal handler, if necessary */
if (![self registerHandlerWithSignal: signo error: outError])
return NO;
/* Add the new callback to the shared state list. */
plcrash_signal_user_callback reg = {
.callback = callback,
.context = context
};
shared_handler_context.callbacks.nasync_prepend(reg);
return YES;
}
可以查看 registerHandlerWithSignal
来查看实现。
PLCrashReporter
将这些崩溃堆栈信息存储后,App就崩溃了,等待下次重启时,就可以取到这些日志,进行上传分析。
系统接口
系统函数的优点在于性能好,但是只能获取简单的信息,无法通过dSYM文件来了解是哪行代码出的问题。
SIGABRT--程序中止命令中止信号
SIGALRM--程序超时信号
SIGFPE--程序浮点异常信号
SIGILL--程序非法指令信号
SIGHUP--程序终端中止信号
SIGINT--程序键盘中断信号
SIGKILL--程序结束接收中止信号
SIGTERM--程序kill中止信号
SIGSTOP--程序键盘中止信号
SIGSEGV--程序无效内存中止信号
SIGBUS--程序内存字节未对齐中止信号
SIGPIPE--程序Socket发送失败中止信号
void InstallSignalHandler(void)
{
signal(SIGHUP, SignalExceptionHandler);
signal(SIGINT, SignalExceptionHandler);
signal(SIGQUIT