iOS应用的crash日志的分析基础

标签: ios 应用 crash | 发表时间:2014-02-10 18:46 | 作者:jasonblog
出处:http://blog.csdn.net
Outline
如何获得crash日志
如何解析crash日志
如何分析crash日志
     1. iOS策略相关
     2. 常见错误标识
     3. 代码bug


一、如何获得crash日志

当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上。这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志例外),对于开发人员定位问题很有帮助。

如果设备就在身边,可以连接设备,打开Xcode - Window - Organizer,在左侧面板中选择Device Logs(可以选择具体设备的Device Logs或者Library下所有设备的Device Logs),然后根据时间排序查看设备上的crash日志。这是开发、测试阶段最经常采用的方式。

如果应用程序已经提交到App Store发布,用户已经安装使用了,那么开发者可以 通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见 iOS: Providing Apple with diagnostics and usage information摘要。

考虑到并不是所有iPhone用户都允许自动发送诊断报告(crash日志),而且对于部分提交到Apple得crash日志,开发者还需要手动去拉取,然后找到对应的符号文件进行解析——这是一件很繁琐的事情。所以实际项目开发中,通常接入现有的crash收集工具( 参考1参考2),或者自己编写一个进行自动化收集、解析和统计汇总。


二、如何解析crash日志

当获得一份crash日志时,我们需要将初始展示的十六进制地址等原始信息映射为源代码级别的方法名称和代码行数,使其对开发人员可读。这个过程称为符号化解析。要成功地符号化解析一份crash日志,我们需要有对应的应用程序二进制文件以及符号(.dSYM)文件。

如果处于开发调试阶段,通常Xcode都能匹配到crash日志对应的二进制文件和符号文件,所以能够帮我们自动解析。

如果处于测试阶段,测试人员已经安装了不同的版本(比如alpha、beta版本),那么需要保存好对应版本的二进制文件和符号文件,以便在应用程序崩溃时对crash日志进行解析。对于这种场景下产生的crash日志,只需要将.crash文件、.app文件和.dSYM文件三者放在同一个目录下,然后将.crash文件拖放到Xcode - Window - Organizer中左侧面板Library下的Device Logs中,即可进行解析。

如果要提交发布,那么我们通常会先执行Clean,再Build,最后通过Product - Archive来打包。这样,Xcode会将二进制文件和符号文件归档在一起,可以通过Organizer中的Archives进行浏览。

这里是一份关于如何解析crash日志的讨论: http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports 。


三、如何分析crash日志

在分析一份crash日志之前,如果开发人员对于常见的错误类型有所了解,那定是极好的。
crash日志的产生来源于两种问题:违反iOS策略被干掉,以及自身的代码bug。

1. iOS策略

1.1 低内存闪退
前面提到大多数crash日志都包含着执行线程的栈调用信息,但是低内存闪退日志除外,这里就先看看低内存闪退日志是什么样的。
我们使用Xcode 5和iOS 7的设备模拟一次低内存闪退,然后通过Organizer查看产生的crash日志,可以发现Process和Type都为Unknown:



而具体的日志内容如下:



第一部分是崩溃信息,包括识别标识、软硬件信息和时间信息等。
第二部分是内存页分配信息,以及当前占用内存最多的进程,上图中为crashTypeDemo。
第三部分是具体的进程列表,描述着每个进程使用内存的情况以及当前状态。在较早的版本中可以在某些进程后面看到“jettisoned”字样,表明这些进程使用过多内存被终止了,而现在我们看到的是“vm-pageshortage”字样。

当iOS检测到内存过低时,它(的VM系统)会发出低内存警告通知,尝试回收一些内存;如果情况没有得到足够的改善,iOS会终止后台应用以回收更多内存;最后,如果内存还是不足,那么正在运行的应用可能会被终止掉。
所以,我们的应用应该合理地响应系统抛出来的低内存警告通知,对一些缓存数据和可重新创建的对象进行释放,同时要避免出现内存泄露等问题。

低内存闪退是由iOS策略决定终止应用程序运行的,同样基于iOS策略的还有Watchdog超时和用户强制退出。

1.2 Watchdog超时
Apple的iOS Developer Library网站上, QA1693文档中描述了Watchdog机制,包括生效场景和表现。如果我们的应用程序对一些特定的UI事件(比如启动、挂起、恢复、结束)响应不及时,Watchdog会把我们的应用程序干掉,并生成一份响应的crash报告。

这份crash报告的有趣之处在于异常代码:“0x8badf00d”,即“ate bad food”。
如果说特定的UI事件比较抽象,那么用代码来直接描述的话,对应的就是(创建一个工程时Xcode自动生成的)UIApplicationDelegate的几个方法:



所以当遇到Watchdog日志时,可以检查下上图几个方法是否有比较重的阻塞UI的动作。

QA1693举的例子是在主线程进行同步网络请求。如果我们是在公司的Wifi环境下使用则一切顺利,但当应用程序发布出去面向很大范围的用户,在各种网络环境下运行,则不可避免地会出现一片Watchdog超时报告。
另一种可能出现问题的场景就是 数据量比较大的情况下进行的数据库版本迁移(同样是在主线程上),这也是促使我写这篇总结的一个直接因素。

1.3 用户强制退出

一看到“用户强制退出”,首先可能想到的双击Home键,然后关闭应用程序。不过这种场景是不会产生crash日志的,因为双击Home键后,所有的应用程序都处于后台状态,而iOS随时都有可能关闭后台进程,所以这种场景没有crash日志。

另一种场景是用户同时按住电源键和Home键,让iPhone重启。这种场景会产生日志(仅验证过一次),但并不针对特定应用程序。

这里指的“用户强制退出”场景,是稍微比较复杂点的操作:先按住电源键,直到出现“滑动关机”的界面时,再按住Home键,这时候当前应用程序会被终止掉,并且产生一份相应事件的crash日志。



通常,用户应该是遇到应用程序卡死,并且影响到了iOS响应,才会进行这样的操作——不过感觉这操作好高级,所以这样的crash日志应该比较少见。

2. 常见错误标识

2.1 Exception codes
上面“用户强制退出”的crash日志中的Exception Codes是“0xdeadfa11”,再上面“Watchdog超时”的crash日志中的Exception Codes是“0x8badf00d”,这些都是特有的Exception codes。
根据官方文档描述,至少有以下几种特定异常代码:

0x8badf00d错误码:Watchdog超时,意为“ate bad food”。

0xdeadfa11错误码:用户强制退出,意为“dead fall”。

0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。



0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。

0xc00010ff错误码:因为太烫了被干掉,意为“cool off”。

0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为“dead lock”。

2.2 Exception types
查看我们的crash分析报告邮件,会发现最经常遇到的错误类型是SEGV(Segmentation Violation,段违例),表明内存操作不当,比如访问一个没有权限的内存地址。
当我们收到 SIGSEGV信号时,可以往以下几个方面考虑:
访问无效内存地址,比如访问Zombie对象;
尝试往只读区域写数据;
解引用空指针;
使用未初始化的指针;
栈溢出;
此外,还有其它常见信号:
SIGABRT:收到Abort信号,可能自身调用abort()或者收到外部发送过来的信号;
SIGBUS:总线错误。与SIGSEGV不同的是,SIGSEGV访问的是无效地址(比如虚存映射不到物理内存),而SIGBUS访问的是有效地址,但总线访问异常(比如地址对齐问题);
SIGILL:尝试执行非法的指令,可能不被识别或者没有权限;
SIGFPE:Floating Point Error,数学计算相关问题(可能不限于浮点计算),比如除零操作;
SIGPIPE:管道另一端没有进程接手数据;

3. 代码bug
此外,比较常见的崩溃基本都源于代码bug,比如数组越界、插空、多线程安全性、访问野指针、发送未实现的selector等。如果引入Core Data,则又有另外一些常见问题,不过这是另一个话题了。

遇到这些bug时,都有比较清楚的错误原因说明,比如“index 0 beyond bounds for empty array”等。需要稍微注意点的是多线程问题,当一时找不到解决思路时,不妨往多线程方面考虑下。


看到这里的移动开发者(iOS/Android),如果有兴趣到阿里巴巴(杭州)工作,可以联系我,或者直接把简历发到 siqin.ljp(at)taobao.com。

作者:jasonblog 发表于2014-2-10 10:46:58 原文链接
阅读:0 评论:0 查看评论

相关 [ios 应用 crash] 推荐:

iOS应用的crash日志的分析基础

- - CSDN博客移动开发推荐文章
一、如何获得crash日志. 当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上. 这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志例外),对于开发人员定位问题很有帮助. 如果设备就在身边,可以连接设备,打开Xcode - Window - Organizer,在左侧面板中选择Device Logs(可以选择具体设备的Device Logs或者Library下所有设备的Device Logs),然后根据时间排序查看设备上的crash日志.

iOS crash 崩溃问题的追踪方法

- - 移动开发 - ITeye博客
在调试程序的时候,总是碰到crash的bug,而且一追踪就是一些汇编的代码,让人特别疑惑. 一般情况下可以通过增加两天断点来解决此问题,方法介绍如下:. 基本上有错误分为以下几种类型:. SIGABRT和EXC_BAD_ACCESS较为特殊,算是比较好跟进. SIGABRT是系统报错,在memery warning之后,系统会把程序强制退出,报的就是这个错误.

android开发之应用Crash自动抓取Log_自动保存崩溃日志到本地

- - CSDN博客推荐文章
应用发生crash之后要查看log,判断问题出在什么地方,可是一旦应用发布出去,就要想办法把用户的崩溃日志拿到分析. 所以要在发生crash之后抓取log,然后上传到服务器,方便开发者查看,现在都有很多第三方做这方面的服务,这里说下如何自己来实现. 其实原理很简单,应用出现异常后,会由默认的异常处理器来处理异常,.

JVM Crash导致的重启

- - 企业架构 - ITeye博客
32操作系统下 发生jvm crash . 从表面看是由于OO导致的. 可以发现程序进程号为924,出现问题的线程号为:912. 可以尝试解决办法:-XX:-DoEscapeAnalysis. CPU:total 4 (4 cores per cpu, 1 threads per core) family 6 model 23 stepping 6, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, tsc.

Android程序Crash时的异常上报

- - CSDN博客移动开发推荐文章
转载请注明来源:http://blog.csdn.net/singwhatiwanna/article/details/17289479. 大家都知道,android应用不可避免的会发生crash,无论你的程序写的多完美,总是无法完全避免crash的发生,可能是由于android系统底层的bug,也可能是由于不充分的机型适配或者是糟糕的网络状况.

Android NDK开发Crash错误定位

- - 极客521 | 极客521
在Android开发中,程序Crash分三种情况:未捕获的异常、ANR(Application Not Responding)和闪退(NDK引发错误). 其中 未捕获的异常根据logcat打印的堆栈信息很容易定位错误. ANR错误也好查,Android规定,应用与用户进行交互时,如果5秒内没有响应用户的操作,则会引发ANR错误,并弹出一个系统提示框,让用户选择继续等待或立即关闭程序.

Android Crash 前的最后抢救

- - SegmentFault 最新的文章
众所周知,当 Andoird 程序发生未捕获的异常的时候,程序会直接 Crash 退出. 而所谓安全气囊,是指在 Crash 发生时捕获异常,然后触发兜底逻辑,在程序退出前做最后的抢救. 在实现安全气囊之前,我们先思考一个问题,像 bugly、sentry 这种监控框架是如何捕获异常并上传堆栈的呢.

Apple:年度最佳 iOS 应用榜单

- jicknan - 爱范儿 · Beats of Bits
过去的一年堪称苹果的丰收年,革命性的 iPad 和大卖特卖的 iPhone 4 的各种故事贯穿了整个 2010,然而,除去优秀的硬件设计,iOS 的真正竞争力,在于它那恐怖的 30 万应用. 今天,苹果公布了 2010 的最佳 iOS 应用榜单(应该是北美的统计). 1:美国人对于职棒的爱超过了一切,在总榜单上,MLB.com 的免费应用甚至超过了愤怒小鸟.

《金融时报》移除iOS应用

- yonghai - Solidot
《金融时报》成为第一家因苹果应用内订阅分成政策而移除iOS应用的世界知名媒体. 金融时报发言人Tom Glover表示,他们是在与苹果友好协商后决定移除应用,表示iTunes对基于广告的应用来说仍然是一个重要渠道. 苹果的新政策要求从应用内内容销售和订阅中提取三成收入. 为了遵循苹果要求,Amazon、Barnes & Noble、Kobo、Google和《华尔街日报》决定从应用内移除购买功能.

iOS应用下载“量价齐升”

- ItTalks - 《商业价值》杂志
专注于研究苹果公司的咨询公司Piper Jaffray’s Gene Munster近期发布了一份研究报告. 报告显示,2011年,iOS设备用户正在以更大的热情购买付费应用,而付费iOS应用的价格也普遍得到提升. Piper Jaffray详细监测了自App Store上线以来,包括终端数量、应用下载数量、付费应用数量、免费应用数量、收入等在内的各种数据.