最近很长一段时间在解决以前程序中存在的BUG,一直在优化优化,从最开始客户反映的6Plus在后台前台切换过程中程序出现闪退开始,我曾经尝试着从苹果官网后台获取Crash报告,结果我神奇的发现,我的错误报告是0,这点很让我意外,然而测试也未测出错误的存在,在这时候接受了某个网友的建议集成第三方错误收集的SDK
Bugtags
,从这个后台我发现了前篇一律的崩溃错误提示
Signal 13 was raised. SIGPIPE
我查到了对这一错误的描述:
管道另一端没有进程接收数据,导致管道破裂而崩溃。
socket或管道,当自己主动关闭,资源被苹果系统回收,对方关闭时,当再次通过socket或pipe的文件描述符发送消息会出现系统级别的崩溃(管道破裂,signal 13。它的级别和内存使用或释放异常一直,由于是系统级别崩溃,所以不能通过@try{}@catch (NSException *exception) {
}捕获到异常,而是直接app崩溃)。
原文链接
http://blog.csdn.net/jia12216/article/details/50844013
这篇博文介绍了出现了这种错误的解释,简单通俗的解释就是服务端回传过来给客户端数据时候,客户端没有了接受者,导致了错误,而且原文也给出了解决方案
方案一:signal(SIGPIPE, SIG_IGN) 忽略此信号,代码具体位置写在main函数中即可
方案二:(setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, SIG_IGN, sizeof(int));
忽略具体的socket信号,sd为具体的socket
但是前两种方案我尝试了第一种(第二种并不适用,我项目中未自己写socket通信),结果显而易见的,然并卵了!!!
这种错误信号是无法忽略掉的,当后台停滞很久再次进入程序还会出现这个闪退问题,经过多方查资料我又找到了另一种方案
方案三:
sigset_t signal_mask;
sigemptyset (&signal_mask);
sigaddset (&signal_mask, SIGPIPE);
原理也是忽略SIGPIPE信号,这种情况确定解决了这个问题,我在测试过程中后台久置并未出现闪退的问题,一定注意的一点事测试需在release
状态下。
我以为我已经解决了这个问题,结果在我集成新的BUG收集SDK(BugHD,原因bugtags免费15天使用)中我又发现了报出了:
1.Signal 6 was raised
错误原因:系统报错
可能导致的原因有以下几种:
对象释放了多次
储存错误
调用了没有实现的方法
2.Signal 11 was raised
错误原因:无效内存引用
可能导致的原因有以下几种:
向一个已经释放的对象发送了消息
在多线程中对一个已经释放的对象没有进行同步操作
没有对变量进行初始化而直接访问这个无效对象
我的内心其实是奔溃的,痛定思痛以后认真的分析了错误的原因:
由于程序进入后台后一段时间,程序被系统挂起,内存回收,导致部分对象内存中已经释放,而由于代码中的循环引用的出现,导致对象没被释放,再次进入前台接收到对象信号,肯定会出现上述错误。
我查看了代码中出现的问题,主要就是这两种问题
1.block中使用self
2.添加了通知,而当本类销毁的时候未移除通知。
当我发现所有类代码中都存在的block中用self,我真的很奔溃,我无力吐槽了,外包的兄弟们长点心吧😄😄😄。。。
附block宏
define WeakObj(o) autoreleasepool{} __weak typeof(o) o##Weak = o;
类中@WeakObj(self);
,然后直接用selfWeak即可。