程序异常捕获-001-UncaughtException

程序的异常捕获:

Crash日志记录的时候是将Crash发生时刻,函数的调用栈,以及线程等信息写入文件 

01-Crash文件的解析

今天就跟大家一起聊聊 iOS Crash文件的组成以及常用的分析工具。 

一、Crash文件结构 

当程序运行Crash的时候,系统会把运行的最后时刻的运行信息记录下来,存储到一个文件中,也就是我们所说的 

Crash文件。iOS的Crash日志通常由以下6各部分组成。 

1、Process Information(进程信息) 

 

Incident Idnetifier-崩溃报告的唯一标识符,不同的CrashCrashReporter Key-设备标识相对应的唯一键值(并非真正的设备的UDID,苹果为了保护用户隐私iOS6以后已经无法 

获取)。通常同一个设备上同一版本的App发生Crash时,该值都是一样的。 

Hardware Model - 代表发生Crash的设备类型,上图中的“iPad4,4”代表iPad Air 

Process - 代表Crash的进程名称,通常都是我们的App的名字, []里面是当时进程的ID 

Path - 可执行程序在手机上的存储位置,注意路径时到XXX.app/XXX,XXX.app其实是作为一个Bundle的,真正的可 执行文件其实是Bundle里面的XXX,感兴趣的可以自己查一下相关资料,有机会我后面也会介绍到 

Identifier-你的App的Indentifier,通常为“com.xxx.yyy”,xxx代表你们公司的域名,yyy代表某一个App 

Version-当前App的版本号,由Info.plist中的两个字段组成,CFBundleShortVersionString and CFBundleVersion 

Code Type-当前App的CPU架构 

Parent Process-当前进程的父进程,由于iOS中App通常都是单进程的,一般父进程都是launchd 

2、Basic Information 

 

 

Date/Time-Crash发生的时间,可读的字符串

OS Version-系统版本,()内的数字代表的时Bulid号

Report Version-Crash日志的格式,目前基本上都是104,不同的version里面包含的字段可能有不同 

3、Exception(非常重要) 

 

 

Exception Type-异常类型 

Exception Subtype-异常子类型 

Crashed Thread-发生异常的线程号 

4、Thread Backtrace 

 

 

发生Crash的线程的Crash调用栈,从上到下分别代表调用顺序,最上面的一个表示抛出异常的位置,依次往下可以看 到API的调用顺序。上图的信息表明本次Crash出现xxxViewController的323行,出错的函数调用为 orderCountLoadFailed。 

5、Thread State 

 

 

Crash时发生时刻,线程的状态,通常我们根据Crash栈即可获取到相关信息,这部分一般不用关心。 

6、Binary Images 

 

 

Crash时刻App加载的所有的库,其中第一行是Crash发生时我们App可执行文件的信息,可以看出为armv7,可执行 文件的包得uuid位c0f......cd65,解析Crash的时候dsym文件的uuid必须和这个一样才能完成Crash的符号化解析。 

二、分析Crash来源

通常来说,crash产生来源于两种问题:违反iOS系统规则导致的crashApp代码逻辑 BUG导致的crash,下面分别对他们进行分析。 

违反iOS系统规则产生crash的三种类型: 

1>内存报警闪退 

iOS检测到内存过低时,它的VM系统会发出低内存警告通知,尝试回收一些内存;如果情况没有得到足够的改善, iOS会终止后台应用以回收更多内存;最后,如果内存还是不足,那么正在运行的应用可能会被终止掉。在Debug模 式下,可以主动将客户端执行的动作逻辑写入一个log文件中,这样程序童鞋可以将内存预警的逻辑写入该log文件, 当发生如下截图中的内存报警时,就是提醒当前客户端性能内存吃紧,可以通过Instruments工具中的Allocations Leaks模块库来发现内存分配问题和内存泄漏问题。 

2>响应超时 

当应用程序对一些特定的事件(比如启动、挂起、恢复、结束)响应不及时,苹果的Watchdog机制会把应用程序干 掉,并生成一份相应的crash日志。这些事件与下列UIApplicationDelegate方法相对应,当遇到Watchdog日志时,可 以检查上图中的几个方法是否有比较重的阻塞UI的动作。 

application:didFinishLaunchingWithOptions: 2 applicationWillResignActive:3 applicationDidEnterBackground:4 applicationWillEnterForeground: 5 applicationDidBecomeActive: 6 applicationWillTerminate: 

3>用户强制退出

一看到用户强制退出,首先可能想到的双击Home键,然后关闭应用程序。不过这种场景一般是不会产生crash日志 的,因为双击Home键后,所有的应用程序都处于后台状态,而iOS随时都有可能关闭后台进程,当应用阻塞界面并停 止响应时这种场景才会产生crash日志。这里指的用户强制退出场景,是稍微比较复杂点的操作:先按住电源键,直 到出现滑动关机的界面时,再按住Home键,这时候当前应用程序会被终止掉,并且产生一份相应事件的crash日 志。 

应用逻辑的Bug 

大多数闪退崩溃日志的产生都是因为应用中的Bug,这种Bug的错误种类有很多,比如: 

SEGV:(Segmentation Violation,段违例),无效内存地址,比如空指针,未初始化指针,栈溢出等; SIGABRT:收到Abort信号,可能自身调用abort()或者收到外部发送过来的信号; SIGBUS:总线错误。与SIGSEGV不同的是,SIGSEGV访问的是无效地址(比如虚存映射不到物理内存),而 SIGBUS访问的是有效地址,但总线访问异常(比如地址对齐问题); SIGILL:尝试执行非法的指令,可能不被识别或者没有权限; 

SIGFPE:Floating Point Error,数学计算相关问题(可能不限于浮点计算),比如除零操作; SIGPIPE:管道另一端没有进程接手数据; 

常见的崩溃原因基本都是代码逻辑问题或资源问题,比如数组越界,访问野指针或者资源不存在,或资源大小写错误

等。

 

三、获取Crash的途径

1、本机 

通过xCode连接测试机器,直接在Device中即可读取到该机器上发生的所有Crash log。 

2、itunes connect通过itunes connect后台获取到用户上报的Crash日志。

3、第三方的Crash收集系统 

有很多优秀的第三方Crash收集系统大大的方便了我们收集Crash,甚至还带了符号化Crash日志的功能。比较常用的 有Crashlytics,Flurry等。 

 

 

 

posted @ 2018-07-03 00:05  淡然微笑_Steven  阅读(3599)  评论(0编辑  收藏  举报