美文网首页
理解 iOS Crash

理解 iOS Crash

作者: coder_那一抹刚吹过的风 | 来源:发表于2021-11-06 22:03 被阅读0次

    作为一名开发人员,如何定位解决线上Crash是每一个必修的课题。那问题来了,Crash 如何产生?作为一名 iOS 开发,我今天主要分享 iOS Crash 相关的内容

    Crash 产生

    Crash 产生一般分两种情况:

    1. 应用程序自己调用退出函数。eg:调用自杀函数 kill()
    2. 系统把你应用杀死。eg:应用内存占用过高时,系统保护机制会把你的应用干掉。

    (各种崩溃场景后续再讨论)
    想清楚以上两个场景之后我们我们来看几个元凶。

    • 软件异常
      软件异常主要来源于两个 API 的调用 kill() 、 pthread_kill() , 而 iOS 中我们常常遇到的 NSException 未捕获、 abort() 函数调用等,都属于这种情况。比如我们常看到 Crash 堆栈中有 pthead_kill 方法的调用。
      (此刻我知道你的内心活动,**从来没掉过啊。没错你是没掉,但是系统库会 eg:libc,刺激不刺激,惊喜不惊喜)
    • 硬件异常
      硬件产生的信号始于处理器 trap,处理器 trap 是平台相关的。出现这种情况,计算机会暂停当前程序,及时转入故障处理。比如我们遇到的野指针崩溃大部分是硬件异常。
    • Mach异常
      这里虽然叫异常,但是要和上面的两种分开来看。我们了解到苹果的内核 xnu 的核心是 Mach , 在 Mach 之上建立了 BSD 层。“Mach异常” 是 “Mach异常处理流程” 的简称。不懂没事,后面有讲解

    除了以上三个大杀器,还有一个是程序语言异常,这个在我们的Crash日志也是比较常见的,但是与以上三个不同,这种异常往往是我们代码逻辑不合理造成的。没错,说的就是看文章的你,为啥会崩溃,你心里一点数都没有吗????这种稍后我也会给大家总结

    接下来我们看一下 Mac OS & iOS 是如何处理这些异常的。以下内容来自“深入解析 Mac OS X & iOS 操作系统”
    软件异常处理:

    软件信号处理流程
    硬件异常处理:
    硬件信号处理流程

    通过上面两张图,我们可以很清楚的看到,无论是软件异常,还是硬件异常,最终都会被转换为信号,然后通过act_set_astbsd()发送给我们的应用进程,唤醒其中的某个线程响应指定操作(记住这句话,我们后续有大用)。此时的信号是 UNIX 信号,如 SIGBUS SIGSEGV SIGABRT SIGKILL 等。此时大家可以去翻翻后台的Crash日志,你会发现好多这中以SIG开头的Crash。具体信号的含义大家可以自行 Google,或者直接点击文章参考参考查看。

    UNIX信号抛出简单流程大致如下:

    Unix 信号产生.jpeg
    附 “Mach异常” 与 “UNIX信号” 的转换关系代码,来自 xnu 中的 bsd/uxkern/ux_exception.c :
    switch(exception) {
    case EXC_BAD_ACCESS:
        if (code == KERN_INVALID_ADDRESS)
            *ux_signal = SIGSEGV;
        else
            *ux_signal = SIGBUS;
        break;
    
    case EXC_BAD_INSTRUCTION:
        *ux_signal = SIGILL;
        break;
    
    case EXC_ARITHMETIC:
        *ux_signal = SIGFPE;
        break;
    
    case EXC_EMULATION:
        *ux_signal = SIGEMT;
        break;
    
    case EXC_SOFTWARE:
        switch (code) {
    
        case EXC_UNIX_BAD_SYSCALL:
        *ux_signal = SIGSYS;
        break;
        case EXC_UNIX_BAD_PIPE:
        *ux_signal = SIGPIPE;
        break;
        case EXC_UNIX_ABORT:
        *ux_signal = SIGABRT;
        break;
        case EXC_SOFT_SIGNAL:
        *ux_signal = SIGKILL;
        break;
        }
        break;
    
    case EXC_BREAKPOINT:
        *ux_signal = SIGTRAP;
        break;
    }
    

    看了以上内容,我想你的内心一定是

    你不要再说了
    老实说以上理解以上内容确实需要你有相当的计算机基础功力才行,为了照顾你的心情,接下来咱们聊点你能看懂的。
    除了上面咱们说道的,还有一种程序语言异常,这种异常通常是程序语言自己封装好的。产生的原因通常是因为程序员编写逻辑错误造成的,没错,就是你自己造的孽。作为iOS程序员,我们主要是关注的是 Objec-C 和 Swift。
    Object-C 的异常的异常主要是NSException对象封装的,比较多,咱们这里看几个比较常见的,文末有参考中有链接大家可以看到所有的异常类型。
    先来个王炸,这个你肯定见过:
    1. NSInvalidArgumentException
      传递非法参数给一个方法时抛出的异常。
      常见场景:

      • NSNutableDictionaryr操作key或value的函数,如setObject:forKey:、removeObjectForKey等等。
      • NSMutableArray操作value的函数,如addObject:、 insertObject:atIndex:等等。
      • NSString操作函数,如initWithString:、initWithFormat:、stringWithString:等等。

      这里要住意多线程操作,这个坑,深到一半人爬不出来,比如我前面的小朋友,直接被搞离职了

    2. NSRangeException:
      尝试访问某些数据范围之外时抛出的异常。
      常见场景:

      • NSArray包含索引的操作,如insertObject:atIndex:、objectAtIndex:等等。
      • NSString包含索引的操作,如characterAtIndex:、getCharacters:range:等等。
    3. NSFileHandleOperationException
      如果尝试确定文件句柄类型失败或尝试读取文件或通道失败,则会抛出此异常。
      常见场景:

      • 空间不足:会提示No space left on devie。
      • 没有读写权限:会提示Bad file descriptor。
      • 读文件失败。

      在操作文件时,要验证文件句柄的有效性,对文件大小进行校验,对存储空间进行判断。

    4. KVO引起的异常:
      常见场景:

      • 多次移除KVO
        抛出NSRangeException异常
      • 添加或移除时keyPath参数为nil
      • 没有实现observeValueForKeyPath方法(非必显, iOS14)

      我在当前 iOS 15的系统测试过,无论是没有移除观察者还是VC推出时没有一处观察者都没出现崩溃。多次移除相同Path时和path名字为nil会出现Crash

    5. iOS Crash之NSMallocException
      常见场景:

      • 分配的空间过大
      • 图像占用空间过大
      • OOM问题。这个主要是程序死循环造成的
    6. NSGenericException
      常见场景:

      • 可变对象遍历过程中发生了改变。

    以上大概就是我们开发和线上应用常见一些异常。至于swift,应为NSexception是Cocoa框架的,swift也绕不过,所以上面的异常,swift也是都有的,当然由于语言上的设计优势,swift出现的可能行降低一些。swift 该只有 try! 解析空。其他欢迎大家补充。
    毕竟是初始 iOS Crash,就给大家分析到这里吧,下一篇我们看一下crash收集和符号化。

    参考文档:
    处理器陷阱
    UNIX 信号
    iOS Crash 分析策略
    野指针
    理解异常类型
    Object-C Exception
    iOS内功篇:浅谈Crash

    相关文章

      网友评论

          本文标题:理解 iOS Crash

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