理解 iOS Crash

作为一名开发人员,如何定位解决线上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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容