4.iOS中crash(崩溃)日志相关

如何获取crash日志?

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

       对于测试阶段,有以下几种方法可以获取到crash日志


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

        2. iTunes同步获取
  大部分用户可能都会使用iTunes软件来管理iPhone或者iPad设备,这时候同步的Crash日志就会同步到电脑上,我们只需要在特定的路径里面寻找即可。
Mac OS X:~/Library/Logs/CrashReporter/MobileDevice
Windows XP:C:\Documents and Settings\Application Data\Apple computer\Logs\CrashReporter
Windows 7/Vista:  C:\Users\计算机登录名\AppData\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice

3.使用第三方软件:itools等
如果你平时不用iTunes,而是使用itools这类第三方的软件对iPhone设备进行管理,也是没问题的。打开itools,在你的设备下,找到“高级功能”,点击“崩溃日志”,然后将需要的日志导出到电脑里面就可以了!

        如果应用程序已经提交到App Store发布,用户已经安装使用了,那么开发者可以通过iTunes(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日志对应的二进制文件和符号文件,所以能够帮我们自动解析。
       网上有 比较详细的三种自己解析的方法,点击打开链接,查了下,第二种用工具 symbolicatecrash比较常用,而且直接可以定位到错误代码。具体方法待研究。

如何分析crash日志?

        

        点击打开链接    这里比较详细的列举了几个崩溃亏日志分析的实例,可以参考一下。

        下面列举以下一些常见的错误标识:

Exception codes:

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

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

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

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

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

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

Exception types:

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

IOS系统中如何捕获和处理崩溃日志呢?    

       1. 在程序启动时加上一个异常捕获监听,用来处理程序崩溃时的回调动作

        NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);

        官方文档介绍:Sets the top-level error-handling function where you can perform last-minute logging before the program terminates.

         UncaughtExceptionHandler是一个函数指针,该函数需要我们实现,可以取自己想要的名字。当程序发生异常崩溃时,该函数会得到调用,这跟C,C++中的回调函数的概念是一样的。

        2.实现自己的处理函数

void UncaughtExceptionHandler(NSException *exception)
{
    NSArray *arr = [exception callStackSymbols];//得到当前调用栈信息
    NSString *reason = [exception reason];//非常重要,就是崩溃的原因
    NSString *name = [exception name];//异常类型
    
    NSLog(@"exception type : %@ \n crash reason : %@ \n call stack info : %@", name, reason, arr);
}
        3. 获取到了崩溃日志,如何发送给开发者呢,目前一般有以下两种方式:

                 将崩溃信息持久化在本地,下次程序启动时,将崩溃信息作为日志发送给开发者。

                 通过邮件发送给开发者。 不过此种方式需要得到用户的许可,因为iOS不能后台发送短信或者邮件,会弹出发送邮件的界面,只有用户点击了发送才可发送。 不过,此种方式最符合苹果的以用户至上的原则。




  


你可能感兴趣的:(4.iOS中crash(崩溃)日志相关)