EXC_BAD_ACCESS的本质详解以及僵尸模式调试原理

原文:What Is EXC_BAD_ACCESS and How to Debug It
有时候,你会遇到由EXC_BAD_ACCESS造成的崩溃。 这篇文章会告诉你什么是EXC_BAD_ACCESS,以及它产生的原因。我还会提供一些EXC_BAD_ACCESS错误的解决方案。
1. 什么是 EXC_BAD_ACCESS?
一旦你理解EXC_BAD_ACCESS的本质,你就会更好地理解这个模糊的名词。这里有一个极为简单的解释,也有一个技术层面的解释。我们首先从简单的解释开始说起。
2. 简单的解释
不管什么时候当你遇到EXC_BAD_ACCESS这个错误,那就意味着你向一个已经释放的对象发送消息。这是最常见的情况,但也有例外,我们将在稍后讨论。
3. EXC_BAD_ACCESS的本质
技术层面的解释有些复杂。在C和Objective-C中,你一直在处理指针。指针无非是存储另一个变量的内存地址的变量。当您向一个对象发送消息时,指向该对象的指针将会被引用。这意味着,你获取了指针所指的内存地址,并访问该存储区域的值。
当该存储器区域不再映射到您的应用时,或者换句话说,该内存区域在你认为使用的时候却没有使用,该内存区域是无法访问的。 这时内核会抛出一个异常( EXC ),表明你的应用程序不能访问该存储器区域(BAD ACCESS) 。
总之,当你碰到EXC_BAD_ACCESS ,这意味着你试图发送消息到的内存块,但内存块无法执行该消息。但是,在某些情况下, EXC_BAD_ACCESS是由被损坏的指针引起的。每当你的应用程序尝试引用损坏的指针,一个异常就会被内核抛出。
4.调试EXC_BAD_ACCESS
调试EXC_BAD_ACCESS可能会非常棘手和令人沮丧。然而,现在EXC_BAD_ACCESS不再是一个谜,它没有想象中的那么可怕。
你需要知道的第一件事是您的应用程序并不一定是在崩溃的那一刻,无法访问内存区域。这就是常使调试EXC_BAD_ACCESS变得困难的原因。
同样受损指针也是如此。当你的指针被损坏时,您的应用程序不会崩溃。同时,如果您在应用程序中来回传递一个受损的指针也不会崩溃。当应用程序试图引用受损指针的时候,就会发生奔溃。
5.僵尸调试模式
僵尸调试模式在过去几年中得到了普及,事实上它们已经出现在Xcode上超过十年。僵尸听起来有点戏剧性,但它实际上是为帮助我们调试EXC_BAD_ACCESS功能而取得一个伟大的名字。让我来解释它是如何工作的。
在Xcode中,您可以启用僵尸对象,这意味着被释放的对象将会以僵尸的形式被保留。换言之,保留释放的对象就是为了调试。这里没有涉及任何魔法。如果您向僵尸对象发送消息,你的应用程序将会由于EXC_BAD_ACCESS而崩溃。
这有什么好处吗?让EXC_BAD_ACCESS难以调试的原因是,你不知道你的应用程序试图访问哪个对象。僵尸对象在许多情况下解决这个问题。通过保留已释放的对象,Xcode可以告诉你你试图访问哪个对象,这使的查找问题原因容易得多。
在Xcode中启用僵尸对象是很容易的。注意,这可能会因的Xcode的版本而不同的。以下方法适用于Xcode的6和7,单击左上角的Edit Scheme,并选中Edit Scheme。
在左侧选中Run ,在上方打开 Diagnostics选项。要启用僵尸对象,勾选 Enable Zombie Objects选框。

如果你现在遇到EXC_BAD_ACCESS ,在Xcode的控制台输出,告诉你该从哪里查找问题。看看下面的例子输出。
-[ChildViewController respondsToSelector:] message sent to deallocated instance 0x17579780
在上面的例子中, Xcode告诉我们, respondsToSelector的消息:被发送到一个僵尸对象。然而,僵尸对象不再是ChildViewController类的一个实例。以前分配给ChildViewController实例的内存区域不再映射到您的应用程序。这为你了解问题产生的根本原因提供一个不错的建议。
不幸的是,僵尸对象将无法保存您的一天每次崩溃的EXC_BAD_ACCESS的记录。既然僵尸对象没有这些方法,那么你可以采取其他的方法进行一些适当的分析。
6.分析
如果僵尸对象不能解决你的问题,那么问题的根源可能就不那么简单了。在这种情况下,您需要仔细看看在应用程序崩溃时执行的代码。这可能是繁琐和耗时的。
为了帮助你发现你的代码的问题,你可以使用Xcode来分析你的代码,帮助你找到出现问题的地方。注意,Xcode分析项目,它会指出每一个潜在的可能出现的问题的地方。
使用Xcode来分析你的项目,从Xcode的 Product菜单选择 Analyze或按 Shift-Command-B.Xcode的将需要片刻的时间,但是当它完成的时候你会在左边的 Issue Navigator看到问题列表。由Analyze发现的问题用蓝色高亮显示。

当你点击一个问题,Xcode的会指向问题代码块,这些正是你要的注意的地方。注意,Xcode仅仅是建议。在某些情况下,这是可能的,问题是不相关的,不固定。

如果你找不到造成EXC_BAD_ACCESS的错误,那就需要你仔细审视Xcode项目,分析其中发现的每一个问题。
7.结论
EXC_BAD_ACCESS是开发者面临的一个共同的问题,它是手动内存管理固有的问题。虽然推行ARC内存管理方式 (自动引用计数)使得EXC_BAD_ACCESS没那么频繁,但他们并没有真正的消失。
http://www.cocoachina.com/articles/15324
EXC_BAD_ACCESS的本质详解以及僵尸模式调试原理的更多相关文章
- javascript设计模式详解之命令模式
每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...
- javascript设计模式详解之策略模式
接上篇命令模式来继续看下js设计模式中另一种常用的模式,策略模式.策略模式也是js开发中常用的一种实例,不要被这么略显深邃的名字给迷惑了.接下来我们慢慢看一下. 一.基本概念与使用场景: 基本概念:定 ...
- 图解SynchronousQueue原理详解-非公平模式
SynchronousQueue原理详解-非公平模式 开篇 说明:本文分析采用的是jdk1.8 约定:下面内容中Ref-xxx代表的是引用地址,引用对应的节点 前面已经讲解了公平模式的内容,今天来讲解 ...
- 详解Mac睡眠模式设置
详解Mac睡眠模式设置 原文链接:http://www.insanelymac.com/forum/index.php?showtopic=281945 需要说明的是,首先这篇文章是针对已经能够成功睡 ...
- 详解Java GC的工作原理+Minor GC、FullGC
详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...
- IE8"开发人员工具"使用详解下(浏览器模式、文本模式、JavaScript调试、探查器)
来源: http://www.cnblogs.com/JustinYoung/archive/2009/04/03/kaifarenyuangongju2.html 在上一篇文章IE8“开发人员工具” ...
- 「JVM」知识点详解一:JVM运行原理详解
前言 JVM 一直都是面试的必考点,大家都知道,但是要把它搞清楚又好像不是特别容易.JVM 的知识点太散,不系统,今天带大家详细的了解一下jvm的运行原理. 正文 1 什么是JVM? JVM是Java ...
- 详解vue的数据binding原理
自从angular火了以后,各种mv*框架喷涌而出,angular虽然比较火,但是他的坑还是蛮多的,还有许多性能问题被人们吐槽.比如坑爹的脏检查机制,数据binding是受人喜爱的,脏检查就有点…性能 ...
- OPCode详解及汇编与反汇编原理
1. 何为OPCode 在计算机科学领域中,操作码(Operation Code, OPCode)被用于描述机器语言指令中,指定要执行某种操作的那部分机器码,构成OPCode的指令格式和规范由处理器的 ...
随机推荐
- Unity-遇到的问题小总结
1. event trigger后面显示不了对应的方法 原因:我是直接把脚本拖拽进去的,这是没有实例化的,拖拽进去的应该是挂载这个脚本的GameObject就可以了 2.制作prefeb 将场景中的单 ...
- java架构之路-(mysql底层原理)Mysql之让我们再深撸一次mysql
让我再深撸一次mysql吧,这次主要以应对面试来说说mysql,大概几个方向,索引结构,查询引擎,索引优化,explain的详解和trace工具的使用. 索引: 我们先来看一下mysql的B+tree ...
- python库之turtle(图形绘制) 开启新的快乐源泉
相信有不少人学习python 都是听了老前辈的推荐 “学python好,python有趣的代码多” 比如说画一只小狮子 这就是今天想要介绍的绘制图形库-turtle 如果也想这样画一只小狮子,或者其他 ...
- Java 基础篇之类与对象
类与对象 类.对象和引用的关系 类和对象的关系 类是对象的模版,对象是类的一个实例,一个类可以有很多对象 一个Java程序中类名相同的类只能有一个,也就是类型不会重名 一个对象只能根据一个类来创建 引 ...
- Python爬虫(二):Requests库
所谓爬虫就是模拟客户端发送网络请求,获取网络响应,并按照一定的规则解析获取的数据并保存的程序.要说 Python 的爬虫必然绕不过 Requests 库. 1 简介 对于 Requests 库,官方文 ...
- Java 基础篇之反射
反射 使用反射获取程序运行时的对象和类的真实信息. 获取 Class 对象 每个类被加载之后,系统会为该类生成一个对应的 Class 对象,通过该 Class 对象可以访问到 JVM 中的这个类. 使 ...
- wordpress访问速度慢
可能是google字体的原因 1.找到wordpress目录下wp-includes/script-loader.php这个文件 2.查找open_sans_font_url这个字段,把后面的font ...
- 织梦cms列表页获取标签
<!-- 标签 --> [field:id runphp='yes'] global $cfg_cmspath; $tags = GetTags(@me); $revalue = ''; ...
- ASP.NET Web API 2系列(二):灵活多样的路由配置
1. 导言 路由系统是请求消息进入ASP.NET Web API消息处理管道的第一道屏障,其根本目的在于利用注册的路由对请求的URL进行解析以确定目标HTTPController和Action的名称, ...
- Python多任务之协程
前言 协程的核心点在于协程的使用,即只需要了解怎么使用协程即可:但如果你想了解协程是怎么实现的,就需要了解依次了解可迭代,迭代器,生成器了: 如果你只想看协程的使用,那么只需要看第一部分内容就行了:如 ...