一次iOS EXC_BAD_ACCESS 的分析解决过程

游戏客户端在断线重连后需要调用SDK方法清空消息缓存数据,但是因为游戏在后台停留时间较长,部分内存被释放,导致出现EXC_BAD_ACCESS。

网上大部分关于EXC_BAD_ACCESS的文章都是写了如何检测,并没有说明如何处理这种问题。当然本文也是基于特定场景下解决了该问题。

什么是EXC_BAD_ACCESS?


EXC_BAD_ACCESS简单的讲就是使用了已经被释放的内存,导致crash。

写Demo测试


ClassA(单例对象) , 一个 strong 的NSMutableArray *marr 吧。

@property (nonatomic, strong) NSMutableArray *marr;

1、场景:


app1退到后台,使用其他app,经过几分钟后,重新进入app1,会调用 [[ClassA sharedIndstance] clean]

clean方法:
1
2
3
- (void)clean {
[self.marr removeAllObjects];
}


2、分析:


A1:
ClassA单例对象被释放
但是每次不是又[ClassA sharedIndstance] 了吗?

A2:
marr 属性被释放,这种怎么讲,单例没释放,反而里面的属性被释放??


经测试,原因为分析1. [ClassA sharedIndstance] 并不能重新init,即使能init,那也是新的内存对象了。

3、测试过程:


1. 新建单例类SingeTonClass,并在xcode设置为MRC.
2. 初始化然后手动release,再初始化。

EXC_BAD_ACCESS1


EXC_BAD_ACCESS2


又尝试了这种方式初始化:如果再dealloc之后重新以 alloc方式初始化,则并非以前的对象了,无意义。

EXC_BAD_ACCESS3

那么到此为止,可能看起来就暂时没办法解决了。冲突点:此类必须使用单例,因为工程里面全部用的这种方式;然后断线重连后必须调用clean方法。

4、最后如何解决?

其实也还是采用分析1的方式,重新初始化单例类[ClassA sharedIndstance]。

为何?问题发生的场景。

因为游戏本身断线重连后要清空缓存消息,相当于重新初始化一次单例类。之前一直在意重新初始化后并非原对象,没有考虑问题发生的场景。

那么重新初始化sharedIndstance时,需要先把原来的单例销毁,方法:
EXC_BAD_ACCESS4

自此,问题解决。