美文网首页
iOS崩溃日志

iOS崩溃日志

作者: Lin__Chuan | 来源:发表于2018-09-20 19:19 被阅读26次

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

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

      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

    image.png

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

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

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

    相关文章

      网友评论

          本文标题:iOS崩溃日志

          本文链接:https://www.haomeiwen.com/subject/fmvnnftx.html