- 简单的理解:当遇到了EXC_BAD_ACCESS异常,意味着访问了一个已经被释放的内存区域。
- 指针层面理解:从C、OC语言来解释,我们平时所操作的对象其实是一个指针,指针是指向另一块存储区域的变量。当向一个对象发送消息,指向这个对象的指针需要被使用,也就是你获得了指针指向的内存地址并且可以访问该内存块的值。当系统不再为你映射该内存块时,换句话说,该内存块已经不能够被你所使用,则不可以再次访问该内存块。 如果再次访问这块内存,发生这种情况时,内核会发送一个异常(EXC),表明您的应用程序无法访问该内存块(BAD ACCESS)。
总之,当遇到了EXC_BAD_ACCESS异常,意味你尝试向一个块已经不能执行这个消息的内存块发送消息。
在某些情况下,访问野指针也会导致EXC_BAD_ACCESS。当应用程序尝试去使用一个野指针的时候,EXC_BAD_ACCESS就会被内核抛出。
调试EXC_BAD_ACCESS
因为当内存块不能被应用程序所使用的时候,并不会立即出现crash,所以导致调试EXC_BAD_ACCESS很麻烦。
对于野指针也是同样的,应用程序不会立即崩溃如果存在野指针,只有当应用程序试图去使用野指针的时候才会崩溃。
僵死对象
僵尸对象听起来有点奇怪,但确实是可以用来帮助调试EXC_BAD_ACCESS问题。非常有效!
Xcode中,可以开启僵尸对象模式。
之所有调试EXC_BAD_ACCESS非常麻烦是因为不知道应用程序要访问哪个对象。僵尸对象可以解决这个问题。
通过让已经被释放的对象存活,Xcode可以告诉我们正在访问哪个被释放的对象,进而找到是什么原因引起的。
僵尸对象并不能把所有的EXC_BAD_ACCESS找出来。所以必须时需要通过下面的一些方式来解决——比如静态分析。
静态分析
如果僵尸对象不能解决问题,可以通过静态分析的方法来提前发现。
可以从Xcode中的Product中选则Analyze
,或者直接Shfit+Command+B
。Xcode将会花点时间把问题的部分有问题的代码罗列出来。类似于:
当点击相关的issue时,就会调到对应的代码位置。
Xcode只是会做出相应的提示,在某些情况下,可能某些情况下不用修复。
- 如果不能准确的定位问题,那么就只通过静态分析一个一个Issue去排查。
总结
EXC_BAD_ACCESS是一个比较常见的但同时也非常麻烦的问题。这是问题是从手动管理内存一直延续下来的,虽然现在大部分都是用ARC,但是并不会意味着EXC_BAD_ACCESS就消失。