iOS崩溃捕获

有些低概率很难重现的闪退会让程序员很头疼,不知道怎么定位问题,其实是有办法捕获崩溃并获得当时的调用堆栈的。拿到堆栈保存下来,找个合适的时机回传到服务器给se分析,可以大大提高修复闪退的工作效率。

首先定义一个捕获异常的NSUncaughtExceptionHandler
void exceptionHandler(NSException *exception) {
    NSLog(@"exit with exception: %@", [exception reason]); // reason为崩溃原因描述
    NSLog(@"%@", [exception callStackSymbols]); // 这个方法可以难道崩溃时的调用堆栈
}

在启动的时候设置未捕获异常的处理函数
NSSetUncaughtExceptionHandler(&exceptionHandler);


==============================
以上是obj-c层面的,如果需要处理c层面的,可参考如下代码

定义要捕获的信号
static int s_fatal_signals[] = {
    SIGABRT,
    SIGBUS,
    SIGFPE,
    SIGILL,
    SIGSEGV,
    SIGTRAP,
    SIGTERM,
    SIGKILL,
};

信号的名称
static const char* s_fatal_signal_names[] = {
    "SIGABRT",
    "SIGBUS",
    "SIGFPE",
    "SIGILL",
    "SIGSEGV",
    "SIGTRAP",
    "SIGTERM",
    "SIGKILL",
};

static int s_fatal_signal_num = sizeof(s_fatal_signals) / sizeof(s_fatal_signals[0]);

获取调用堆栈的函数
+ (NSArray *)backtrace {
void *callstack[128];
int frames = backtrace(callstack, 128);
char **strs = backtrace_symbols(callstack, frames);

NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
for (int i = 0; i < frames; ++i) {
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);

return backtrace;
}

信号处理函数
void signalHandler(int signal) {
    for (int i = 0; i < s_fatal_signal_num; ++i) {
        if (signal == s_fatal_signals[i]) {
            NSLog(@"exit with signal: %s", s_fatal_signal_names[i]);
            NSLog(@"%@", [AppDelegate backtrace]);
            break;
        }
    }
}

注册捕获信号的方法,启动的时候调用
void InitCrashReport() {
    // linux错误信号捕获
    for (int i = 0; i < s_fatal_signal_num; ++i) {
        signal(s_fatal_signals[i], signalHandler);
    }
}

猜你喜欢

转载自sking777.iteye.com/blog/2004258