crash

来源:iOS崩溃crash大解析 -

1.上线崩溃日志获取

App上线以后苹果就会自动捕捉崩溃信息,当App出现Crash后iOS系统就会记录崩溃日志并上传到Appple的服务器。前提是需要用户同意 “与应用开发者共享”

步骤为 设置->隐私->诊断与用量->与应用开发者共享

官方提供的崩溃信息并不是实时的,只能查看两天之前的崩溃信息。需要实时的可以使用第三方工具。

2.本地崩溃日志获取

崩溃日志可以从xcode里打开Devices看到对应手机的一些奔溃信息。

3.通过二进制文件来分析崩溃信息

dSYM文件其实是一个目录,在子目录中包含了一个16进制的保存函数地址映射信息的中转文件,所有Debug的symbols都在这个文件中(包括文件名、函数名、行号等),所以也称之为调试符号信息文件。

符号表就是用来符号化 crash log(崩溃日志)。crash log中有一些方法16进制的内存地址等,通过符号表就能找到对应的能够直观看到的方法名之类。


4.第三方崩溃日志获取

来源 漫谈iOS Crash收集框架 | 程序媛念茜 — 单线程妞


所有Mach异常都在host层被ux_exception转换为相应的Unix信号,并通过threadsignal将信号投递到出错的线程。

EXC_BAD_ACCESS (SIGSEGV)表示的意思是:Mach层的EXC_BAD_ACCESS异常,在host层被转换成SIGSEGV信号投递到出错的线程。既然最终以信号的方式投递到出错的线程,那么就可以通过注册signalHandler来捕获信号:

signal(SIGSEGV,signalHandler);

对于应用级异常NSException,可通过注册NSUncaughtExceptionHandler捕获异常信息:

static void my_uncaught_exception_handler (NSException *exception) { //这里可以取到 NSException 信息}

NSSetUncaughtExceptionHandler(&my_uncaught_exception_handler);

iOS异常捕获 | 向晨宇的技术博客

    //启动异常处理

    InstallSignalHandler();//信号量截断

    InstallUncaughtExceptionHandler();//系统异常捕获


void InstallSignalHandler(void){         

signal(SIGHUP, SignalHandler);   

signal(SIGINT, SignalHandler);   

signal(SIGQUIT, SignalHandler);       

signal(SIGABRT, SignalHandler);   

signal(SIGILL, SignalHandler);   

signal(SIGSEGV, SignalHandler);   

signal(SIGFPE, SignalHandler);   

signal(SIGBUS, SignalHandler);   

signal(SIGPIPE, SignalHandler);

}

4.2两个收集崩溃日志的冲突

iOS友盟和其他崩溃收集库共存时的冲突问题 - zh_iOS的个人空间 - 开源中国

先通过  NSGetUncaughtExceptionHandler(); 拿到之前日志库处理exception 的 handler,然后通过 NSSetUncaughtExceptionHandler();设置自己处理exception 的handler, 在自己的handler 处理完异常之后,再将异常塞给之前的handler。_previousHandler(exception)

5.崩溃的分类

1)野指针 

如何定位Obj-C野指针随机Crash(一):先提高野指针Crash率 - CSDN博客

野指针定位

1.1)对象释放后在内存上填上不可访问的数据,xcode的Enable Scribble就是这个作用。

1.2)   我们要重写对象释放的接口,重写哪个呢?NSObject的dealloc、runtime的 object_dispose,C的free应该都是可以,但是各有优点,我选择的是覆盖面最广的free,free是C的函数,重写了它之后还可以顺带解决一部分C的野指针问题。

1.3)NSZombieEnabled 僵尸模式

启用了NSZombieEnabled的话,它会用一个僵尸来替换默认的dealloc实现,也就是在引用计数降到0时,该僵尸实现会将该对象转换成僵尸对象。僵尸对象的作用是在你向它发送消息时,它会显示一段日志并自动跳入调试器。

1.4)如果崩溃是发生在当前调用栈,通过上面的做法,系统就会把崩溃原因定位到具体代码中。但是,如果崩溃不在当前调用栈,系统就仅仅只能把崩溃地址告诉我们,而没办法定位到具体代码,这样我们也没法去修改错误。这时就可以修改scheme,让xcode记录每个地址alloc的历史,这样我们就可以用命令把这个地址还原出来。

1.5)Enable Address Sanitizer(地址消毒剂)

在Xcode 7上直接使用Clang Address Sanitizer - CocoaChina_让移动开发更简单

1.6)Static Analyzer(静态分析)

1.7)unrecognized selector send to instancd 快速定位

在debug navigator的断点栏里添加Create Symbolic Breakpoint。

在Symbolic中填写如下方法签名:

-[NSObject(NSObject) doesNotRecognizeSelector:]

设置完成后再遇到类似的错误就会定位到具体的代码。

1. EXC_BAD_ACCESS   通常是由于内存管理问题而引起的时

2.SIGABRT   调用了不存在的方法。

2)新老操作系统兼容

3)本地存储的数据结构改变

4).访问的数据为空或访问数据类型不对

5)主线程UI长时间卡死,被系统杀掉

你可能感兴趣的:(crash)