美文网首页
iOS开发-Crash捕捉

iOS开发-Crash捕捉

作者: Henry________ | 来源:发表于2021-06-22 23:08 被阅读0次

    1、手动捕捉crash

    即使有了bugly,也需要知道奔溃是如何捕捉的。
    注意:自定义NSSetUncaughtExceptionHandler之后,会导致bugly失效,需要注意!!

    void UncaughtExceptionHandler(NSException *exception) {
        NSArray *arr = [exception callStackSymbols];
        NSString *reason = [exception reason];
        NSString *name = [exception name];
        NSLog(@"\n%@\n%@\n%@",arr,reason,name);
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            //在可能发生奔溃之前就需要完成注册
            NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
    }
    
    • 可以将奔溃收集起来后上传服务器。

    2、自定义NSException

     //创建异常
        NSString *exceptionName = @"hi,我是一个异常";
        NSString *excaptionReason = @"我不开心了,所以我要让程序崩溃";
        NSDictionary *exceptionUserInfo = nil;
        NSException *exception = [NSException exceptionWithName:exceptionName reason:excaptionReason userInfo:exceptionUserInfo];
        
        //抛出异常
        @throw exception;
    
    • 当然NSException的强大并没有完全展示出来。

    3、系统是如何触发自定义奔溃

    3.1 在_objc_init中完成exception初始化

      //runtime的初始化函数
    void _objc_init(void)
    {
        ...
        //crash奔溃的处理
        exception_init();
    }
    
    void exception_init(void)
    {
        //  _objc_terminate是一个函数指针 
        old_terminate = std::set_terminate(&_objc_terminate);
    }
    
    //系统出现crash都会来到这个函数
    static void _objc_terminate(void)
    {
        if (! __cxa_current_exception_type()) {
            // No current exception.
            (*old_terminate)();
        }
        else {
            // There is a current exception. Check if it's an objc exception.
            @try {
                __cxa_rethrow();
            } @catch (id e) {
                //系统奔溃之后会调用这个uncaught_handler指针函数
                (*uncaught_handler)((id)e);
                 (*old_terminate)();
            } @catch (...) {
                // It's not an objc object. Continue to C++ terminate.
                (*old_terminate)();
            }
        }
    }
    

    3.2 uncaught_handler

    // uncaught_handler 的默认值,什么处理都不做
    static void _objc_default_uncaught_exception_handler(id exception)
    {}
    
    static objc_uncaught_exception_handler uncaught_handler = _objc_default_uncaught_exception_handler;
    
    • uncaught_handler是一个函数指针。

    3.3 objc_setUncaughtExceptionHandler

    //通过该函数完成uncaught_handler的自定义赋值
    objc_uncaught_exception_handler
    objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn)
    {
        ...
        uncaught_handler = fn;
    
        return result;
    }
    
    • uncaught_handler的指针指向了自定义的方法,也就是文章最开始的UncaughtExceptionHandler函数;等待_objc_terminate的函数调用。

    3.4 NSSetUncaughtExceptionHandler和objc_setUncaughtExceptionHandler关系

    函数NSSetUncaughtExceptionHandler是基于CoreFounation的上层封装,底层是objc_setUncaughtExceptionHandler这个函数。

    • callUncaughtHandler是NSSetUncaughtExceptionHandler中完成的赋值,代码就不一一呈现了。

    相关文章

      网友评论

          本文标题:iOS开发-Crash捕捉

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