iOS Crash异常捕获及快速分析

1.前言

  • crash认识
  • 一套系统、一款app、一个功能、甚至一行代码都可能会出现crash,crash伴随着我们的日常生活,如果我们正在玩游戏,LOL打团时,游戏闪退、电脑死机,那就想要跳起来砸键盘了。质量太差的产品,会导致产品负面评价越来越多,用户流失越来越严重,如果在关键环节出现了crash,比如下单、支付等,那就会造成直接损失。作为技术开发,我们对于这种问题要抱有零容忍的态度,虽然我们不可能做到 0 crash,但是我们要尽量避免项目中存在的crash
  • 为什么没有0 crash
  • crash的原因有很多,在工作中我们也有很多方法去避免造成crash,比如自定义一个安全处理方法,做好异常crash因素判断。但是为什么没有一个0crash的系统呢,就不能提供给我们绝对稳定可靠的API吗?
  • 个人认为,每个API的设计都有其作用价值。比如iOS系统提供的[NSAarray objectAtIndex:]方法,如果出现越界就会crash,在项目中也有[NSArray safetyObjctAtIndex:]这样的自定义安全处理方法,越界时返回nil,但是返回nil,就一定是安全的吗?一定是符合所有场景需求的吗?比如某一个代码异常时,后面的代码是否应该执行,执行是否会带来其他的负面影响

2.异常指标

当开发阶段出现crash时,我们可以直接通过xcode定位crash堆栈,在测试阶段crash时,我们勉强还可以直接拿到测试机连接xcode查看日志,但是线上用户或者拿不到crash测试机的情况下,我们需要自己收集crash日志

造成crash的异常主要类型

  • Objective-C uncaughtException异常
    • 这类异常通常可以手动捕获,处理@try...@catch...@finallly,在项目中有很多地方使用
NSArray *arr = @[@1,@2];
@try {
  [arr objectAtIndex:3];
} @catch (NSException *exp){

} @finally {

}
  • NSInvalidArgumentException,非法参数
    • nil参数
      • unrecognized selector sendt to instance
      • ...
    • NSRangeException,越界异常
  • 数组,字符串获取下标
  • NSGenericException,通用异常
  • for ...in 循环中对可遍数组进行增加或者删除,在for( ; ; )中不会造成crash,但是容易造成逻辑上的错误,需要注意
  • NSMallocException,内存分配异常
NSMutableData *mData = [[NSMutableData alloc] initWithCapacity:1];
NSUInteger len = 1844674407370955161;
[mData increaseLengthBy:len];


*** Terminating app due to uncaught exception 'NSMallocException', 
reason: 'Failed to grow buffer'
  • Mach异常
    • 先看下OSX和iOS的系统结构,了解几个基本概念



  • Mach的职责主要是进程和线程抽象、虚拟内存管理、任务调度、进程间通信和消息传递机制等
  • BSD层则在Mach之上,提供一套可靠且更现代的API,提供了POSIX(可移植操作系统接口)兼容性。
  • Mach异常是指最底层的内核级异常,
  • Mach异常处理流程


  • BSD Signals
    • Mach已经通过异常机制提供了底层的陷阱处理,而BSD则在异常机制之上构建了信号处理机制。硬件产生的信号被Mach捕捉,然后转换为对应的UNIX信号。为了维护一个统一的机制,操作系统和用户尝试的信号首先被转换为Mach异常,然后再转换为信号(Signals),如下图所示:


  • 信号可以看做是对硬件异常跟软件异常的封装,需要处理的signals
static const int g_fatalSignals[] =
{
 SIGABRT,//调用abort生成的信号,有可能是NSException也有可能是Mach
 SIGBUS,//非法地址
 SIGFPE,//算术运算错误
 SIGILL,//执行非法指令
 SIGPIPE,//进程间通信产生,通信管道破裂
 SIGSEGV,//非法访问地址,比如野指针,通常是对象的异常释放,指针未清空
 SIGSYS,//非法的系统调用
 SIGTRAP,//断点指令,一般出现在debug调试时
};
  • Mach exception和Signal转换关系


3.crash收集

  • Objective-C uncaughtException可以通过NSSetUncaughtExceptionHandler系统回调进行捕获
  • Mach异常,BSD将mach异常最终都转换为信号异常,所以我们只需要捕捉那些fatal signals,如果开发者没有捕获Mach异常,则会被host层的方法ux_exception()将异常转换为对应的UNIX信号,并通过方法threadsignal()将信号投递到出错线程。可以通过方法signal(x, SignalHandler)来捕获single。
  • C++ exceptions使用系统封装好的函数std::set_terminate(CPPExceptionTerminate)来设置回调
  • 未被try catchNSException会发出killpthread_kill信号-> Mach异常-> Unix信号(SIGABRT),但是SIGABRT在处理收集信息时,获取当前堆栈时获取不到,所以采用NSSetUncaughtExceptionHandler,可以参考KSCrash 源码

4.Crash快速分析

  • 当我们拿到crash日志时,应首先从crash Typecrash thread 快速定位到造成crash的代码段。之所以首先要看这两个,是因为type能大致知道crash的类型,如果是OC类型的异常,那基本上处理起来比较简单,如果是mach signals类型的,通过查看造成crash的线程堆栈,也能快速定位到方法,举个实际项目中的例子:

线上有个偶现的crash,crash Type为SIGSEGV,且thread不定,子线程,主线程都会存在,但是代码段相同,由于SIGSEGV是野指针异常类型,且由于在多线程中都会触发,说明问题基本上是多线程的对象读写安全问题

5.参考资料

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

推荐阅读更多精彩内容