iOS 开发常见崩溃分析

iOS 开发常见崩溃分析

  1. abort(): 函数首先解除进程对SIGABRT信号的阻止,然后向调用进程发送该信号。abort()函数会导致进程的异常终止除非SIGABRT信号被捕捉并且信号处理句柄没有返回

  2. CorruptMalloc: 堆内存腐化,也就是说默认分配的内存地址很小,但是使用时却超过我们分配的空间(默认一般是不会崩溃的,但是超过一定数量的话就会造成崩溃,一般超过一个 PAGE_SIZE 大小就会崩溃),Xcode 一般提示如下错误: EXC_BAD_ACCESS (code=EXC_I386_GPFLT), 大牛解释:(Basically, the memory allocator allocates pages of memory at once for use by programs, and it gives you a pointer within them (making sure the following space is free for use). Since these pages are usually bigger than 8KiB, you have no issue in your mini-program. But if a larger program is allocating larger amounts of memory and writing further and further past the end of your allocated space, then you’ll end up attempting to write into unallocated memory (or memory used by another program!), thus corrupting memory.)

  3. userCorruptObject : 非法对象使用,(__bridge id)将一个 C 指针转换 OC 对象时容易出现,音视频领域常见该问题。

    注:code=1, address=0x7fff0dd3fc70
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7fff0dd3fc70)
    frame #0: 0x0000000105b63997  libobjc.A.dylib`objc_msgSend + 23
    
    Demo:
        // Random data
    void* pointers[] = {NULL, NULL, NULL};
    void* randomData[] = {
        (void*)"a",
        (void*)"b",
        (void*)pointers,
        (void*)"d",
        (void*)"e",
        (void*)"f"};
    
    // A corrupted/under-retained/re-used piece of memory
    struct {void* isa;} corruptObj = {randomData};
    
    // Message an invalid/corrupt object.
    // This will deadlock if called in a crash handler.
    [(__bridge id)&corruptObj class];
    
  4. C++ execetion: C++ 语言抛出了的异常信息,

     libc++abi.dylib: terminating with uncaught exception of type MyException:
  5. dereferenceBadPointer: 坏指针引用(无效指针引用)

    注:错误指针: address=0xffffffffffffffff
    
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xffffffffffffffff)
    * frame #0: 0x000000010fc5739b Crash-Tester`::-[Crasher dereferenceBadPointer](self=0x0000604000005160, _cmd="dereferenceBadPointer") at Crasher.mm:95
    
    
    char* ptr = (char*)-1;
    *ptr = 1;
  6. dereferenceNullPointer: 引用空指针

    注:空指针 address=0x0
    
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    * frame #0: 0x00000001000e13b3 Crash-Tester`::-[Crasher dereferenceNullPointer](self=0x0000600000208730, _cmd="dereferenceNullPointer") at Crasher.mm:100
    
    int* g_crasher_null_ptr = NULL;
    *g_crasher_null_ptr = 1;
  7. stackOverflow : 堆益处崩溃

    
    注: address=0x7ffeed45fff8,code=2
    
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ffeed45fff8)
    * frame #0: 0x0000000101fa15b8 Crash-Tester`::-[Crasher causeStackOverflow](self=<unavailable>, _cmd=<unavailable>) at Crasher.mm:136
    
    - (void) causeStackOverflow
    {
        [self causeStackOverflow];
    }
  8. Div0:除以 0 崩溃

    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
    * frame #0: 0x000000010e50f63e Crash-Tester`::-[Crasher doDiv0](self=0x0000600000006240, _cmd="doDiv0") at Crasher.mm:149
  9. IllegalInstruction: 非法指令,无效数据转换成函数

     注: address=0x7ffee57c0bb0,code=2
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7ffee57c0bb0)
    frame #0: 0x00007ffee57c0bb0
    
    - (void) doIllegalInstruction
    {
        unsigned int data[] = {0x11111111, 0x11111111};
        void (*funcptr)() = (void (*)())data;
        funcptr();
    }
  10. accessDeallocatedObject: 获取已经释放的对象

    
    注:code=EXC_I386_GPFLT
    
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x0000000111e4fc9a libobjc.A.dylib`objc_retain + 10
    
    @property(nonatomic, readwrite, assign) id ref;
    
    RefHolder* ref = [RefHolder new];
    ref.ref = [NSArray arrayWithObjects:@"test1", @"test2", nil];
    
    dispatch_async(dispatch_get_main_queue(), ^
    {
       NSLog(@"Object = %@", [ref.ref objectAtIndex:1]);
    });
  11. accessDeallocatedPtrProxy: 获取已经释放的代理,(这个也挺常见的)

    
    注:相关崩溃信息和 accessDeallocatedObject 一致
    
    - (void) accessDeallocatedPtrProxy
    {
        RefHolder* ref = [RefHolder new];
        ref.ref = [MyProxy alloc];
    
        dispatch_async(dispatch_get_main_queue(), ^
        {
           NSLog(@"Object = %@", ref.ref);
        });
    }
  12. deadlock: 线程死锁

    - (void) deadlock
    {
        [self.lock lock];
        [NSThread sleepForTimeInterval:0.2f];
        dispatch_async(dispatch_get_main_queue(), ^
       {
           [self.lock lock];
       });
    }
    
  13. NSExcetion: iOS 自带崩溃信息

    这种崩溃一蹦可以通过 iOS 的自带方法检测处理啊,调用 NSSetUncaughtExceptionHandler 这个方法可以设置异常捕捉的回调方法,发生异常时系统回回调该方法,做好日志保存上传即可,注意,在使用第三方异常捕捉工具时请记住链式传递,否则会导致第三方捕捉工具无法正常使用的问题。
    例如:
    previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
    系统我们方法之后再调用 previousUncaughtExceptionHandler(excetion)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章