iOS崩溃日志

程序什么时候会造成崩溃?

会引发程序运行崩溃基本有两种情况

    1. c++语言层面的错误,比如野指针,除零,内存访问异常等, 这种可以通过信号机制来捕获, 判断信号, 大概知道是什么问题.
    1. 未捕获异常(Uncaught Exception), 可以通过捕获这个异常来做判断.
Uncaught Exception

1.NSException对象
(1) reason:崩溃原因。
(2) callStackSymbols:调用堆栈。
(3) name:崩溃名称
(4) userInfo:崩溃对象。

  • 情况一: 通过try - catch 捕获抛出的异常
@try {
   [@"str" substringFromIndex:100];
} @catch (NSException *exception) {
   NSLog(@"==>%@==>%@", exception.name, exception.reason);
} @finally {
   NSLog(@"finally");
}

这种只能对特定代码做异常捕获, 捕获完之后, exception不会抛出, 程序继续运行.

  • 情况二: 通过 NSSetUncaughtExceptionHandler 设置异常捕获
void uncaughtExceptionHandler(NSException *exception){
    
    NSArray *stackArry= [exception callStackSymbols];
    
    NSString *reason = [exception reason];
    
    NSString *name = [exception name];
    
    NSString *exceptionInfo = [NSString stringWithFormat:@"Exception name:%@\nException reatoin:%@\nException stack :%@",name,reason,stackArry];
}

+ (void)setDefaultHandler {
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
}

当程序运行抛出 exception 时, uncaughtExceptionHandler 会自动捕获异常, 捕获到之后可以自己做处理, 本地分析, 或者上传到服务端收集起来.
这种异常捕获完之后, 因为 exception 本质上来说没有被处理, 程序一样会崩溃.

Signal信号

程序运行报signal, 我遇到的挺少的, 大部分异常都是被Xcode内部处理过的,
如果需要捕获这类异常, 可以这样做

static int s_fatal_signals[] = {
    SIGABRT,
    SIGBUS,
    SIGFPE,
    SIGILL,
    SIGSEGV,
    SIGTRAP,
    SIGTERM,
    SIGKILL,
};
static int s_fatal_signal_num = sizeof(s_fatal_signals) / sizeof(s_fatal_signals[0]);

+(void)startCrashLog
{
    for(int i = 0; i < s_fatal_signal_num; i++) {
        signal(s_fatal_signals[i], SignalHandler);
    }
}

// 处理捕获的信号值, 每一个信号对应一种错误
void SignalHandler(int signal){
    NSLog(@"signal: %d", signal);

  // 可以在这里面通过backtrace, 包装堆栈信息和信号值, 再做分析, 我觉得意义不是很大
    void* callstack[128];
    int frames = backtrace(callstack, 128);
    char **strs = backtrace_symbols(callstack, frames);
    int I;
    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (i = 0;i < 4;i++){
        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    backtrace addObject:[NSString stringWithFormat:@"signal: %d", signal];
    free(strs);

    NSLog(@"=====>>>>>堆栈<<<<<=====\n%@",backtrace);
}

题外话: backtrace

iOS崩溃日志_第1张图片
image.png

通过调用callStackSymbols 可以看到当前线程的堆栈信息,
在底层是通过 backtracebacktrace_symbols 函数打印调用栈信息

  • backtrace函数用来获取当前线程的调用堆栈, 获取的信息将会被存放在buffer中,它是一个指针数组.
  • backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组,
    这里已经自动做了符号化. 而不是单单的内存地址.
iOS崩溃日志_第2张图片
image.png

参考
iOS崩溃收集
android和iOS平台的崩溃捕获和收集
利用backtrace和backtrace_symbols函数打印调用栈信息

你可能感兴趣的:(iOS崩溃日志)