EXC_BAD_ACCESS算是一个比较常见的错误,大部分情况下,它出现在某个对象还未初始化或已被释放后,还去试图访问这个对象的时候,即是在出现悬挂指针的时候(当然也有非悬挂指针导致的EXC_BAD_ACCESS)。在MRC机制下,EXC_BAD_ACCESS相对会出现得比较多,毕竟手动管理引用计数比较可能会数错。

  在ARC机制下就出现得比较少了,我自己就遇到过几次,可惜基本都忘了记下来,今天就准备试一试如何制造出一个EXC_BAD_ACCESS。

1、首先考虑到悬挂指针。悬挂指针的出现有两种可能:指针指向的对象未初始化,或者指针指向的对象已被释放。

  那么就先新建一个继承自UIView的类Square,并在ViewController中定义一个Square类的属性,正常情况下,代码应该是这样的:

  运行效果如下:

  考虑到悬挂指针的出现有两种可能:指针指向的对象未初始化;指针指向的对象已被释放。那么就分两种情况来处理:

(1)、对于第一种情况,只给这个Square类属性分配内存,不做初始化,代码与运行结果如下:

  代码不负所望地crash了,EXC_BAD_ACCESS。

(2)、接下试图制造第二种悬挂指针,指针指向已释放的对象。首先在Square类里重写dealloc方法,用以监听对象的释放:

  接着将代码修改如下:

  输出结果如下:

  可以看到对象确实已经释放了,但是却没有crash,self.s被指向了nil。在这种情况下并没有出现EXC_BAD_ACCESS,说明在当指针所指对象已被释放的情况下,ARC机制会让指针变成空指针,避免了出现悬挂指针,也就导致不了EXC_BAD_ACCESS了。

  同时,viewDidLoad的最后一句也就不会执行了。

2、我隐约记得有一次在使用UITableView的时候出现过EXC_BAD_ACCESS,似乎是在使用cellForRowAtIndexPath:去取某个没显示在页面上的cell的时候出现的,于是尝试将代码修改如下:

  运行后并没有出现crash,而在tableView:didSelectRowAtIndexPath:方法中有一个打印,打印的结果如下:

  说明这也变成了一个空指针,并不会导致EXC_BAD_ACCESS。这种情况需要以后使用UITableView的时候继续留意。

3、最后还有一种非悬挂指针导致的EXC_BAD_ACCESS的情况,即是在使用Block的时候。演示代码如下:

  可以看到,两种情况都crash了,只要Block没有值,调用的时候就会导致EXC_BAD_ACCESS。因为Block是分配在栈上不是分配在堆上的,所以并不关指针什么事,纯粹就是Block为赋值或者为空值的时候,调用它会访问到栈上错误的内容,EXC_BAD_ACCESS。

  基于此,每次使用Block的时候,都应该先判断一下是否为空。

格而知之4:寻找EXC_BAD_ACCESS的更多相关文章

  1. 格而知之3:Core Data的基本使用

    最近准备做一个随手笔记类的app给自己用,考虑到从未使用过Core Data,就决定用Core Data来做数据存储.在网上参考了一些Core Data的资料后,用一天的时间写了这个demo,主要测试 ...

  2. 格而知之16:我所理解的Block(3)

    23.在前文中的例子中,Block结构体里的isa指针还没有详细讲解,这个指针都被置向了_NSConcreteStackBlock,它标识了Block的类型. 其实除了_NSConcreteStack ...

  3. 格而知之16:我所理解的Block(2)

    11.那么Block到底是怎么实现的呢?试一试通过将Block 的代码转换成普通C语言代码来查看它的实现过程. 要将OC代码转换成C语言代码,可以使用clang编译的一个命令: 通过这个命令能把指定文 ...

  4. 格而知之15:我所理解的Block(1)

    1.Block 本质上是一个struct结构体,在这个结构体中,最重要的成员是一个函数(当然除函数外还有其他重要的成员). 2.在开始解析Block之前,首先来回顾一下Block的格式.Block相关 ...

  5. 格而知之9:一些关于GCD的笔记

    1.最近在重读当年刚开始学习多线程时的笔记,发觉其中有一些地方还是比较容易模糊,于是整理这篇笔记记录一下. 执行方式和队列 2.队列用来存放管理要执行的任务,它分为并发队列(Concurrent Di ...

  6. 格而知之8:我所理解的Runtime(3)

    关联对象 14.使用Category对类进行拓展的时候,只能添加方法,而不适合添加属性(可以添加属性,也可以正常使用get方法和set方法,只是不会自动生成以下划线开头命名的成员变量). 可以通过关联 ...

  7. 格而知之7:我所理解的Runtime(2)

    消息发送(Messaging) 8.以上便是runtime相关的一些数据结构,接下来我们回看一开始的疑问: objc_msgSend()函数在执行的过程中是如何找到对应的类,找到对应的方法实现的呢? ...

  8. 格而知之6:我所理解的Runtime(1)

    基本简介 1.根据官方文档,OC有一个特性:它会尽可能把一些决定从编译时和链接时推迟到运行时才处理,所以这门语言需要的就不只是一个编译器,它还需要一个runtime系统来处理那些已经被编译过的代码. ...

  9. 格而知之5:我所理解的Run Loop

    1.什么是Run Loop? (1).Run Loop是线程的一项基础配备,它的主要作用是来让某一条线程在有任务的时候工作.没有任务的时候休眠. (2).线程和 Run Loop 之间的关系是一一对应 ...

随机推荐

  1. 要理解javascript中间apply和call

    apply和call它是javascript一个非常重要的方法,.虽然与程序平时很少接触,但JS到处都在使用这个框架2方法. 2个方法是在Function.prototype中.也就是说每一个JS函数 ...

  2. js获取名字为XX的标签

    $("input[name='XX']"); <input name="address_select" type="radio" va ...

  3. ASP.NET导入Excel到SQL数据库

    protected void btnChange_Click(object sender, EventArgs e) { UserInfoClass tClass = (UserInfoClass)S ...

  4. 配置元素customErrors

    Asp.net配置文件的配置方式,其实在MSDN里面是写得最清楚的了.可惜之前一直未曾了解到MSDN的强大. 先贴个地址:http://msdn.microsoft.com/zh-cn/library ...

  5. 原创:C sharp 中 Enum的几点小 Tips

    (1)为什么要使用Enum? ♥ enums枚举是值类型,数据直接存储在栈中,而不是使用引用和真实数据的隔离方式来存储.enum student{a,b,c,d,e},其中enum代表student为 ...

  6. javascript延迟加载及异步(defer和async)

    一直以来写代码的时候的常用习惯就是吧所有的js文件直接加载在文档的head标签里面,在写js文件的时候有时候获取一些文件对象的时候为空对象,这是由于文档结构还没有加载完,但是js文件已经加载完.也就是 ...

  7. Qt通过odbc读取excel数据

    传统的读取方式是通过Excel.Application,这种方式不仅操作繁琐,而且速度也不快. 通过odbc读取,可以使用select语句直接读取整个工作表,处理excel数据就跟数据库一样方便. 当 ...

  8. VLC的相关文档以及javascript接口

    参看下面链接:VLC相关文档

  9. Qt之等待提示框三(QLabel进行多图片切换)

    之前分享过的等待提示框有用QMovie播放gif图片实现的,也有纯代码实现的,今天再次分享另一种实现方式,如题目所示:QLabel进行图片的切换!     进行用户登录的时候,往往都需要后台线程进行用 ...

  10. 解决MySQL中文乱码的问题

    遇到中文乱码问题,首先用status命令检查数据库的配置,如下: 上图会显示数据库配置的各项信息. 还可以用 show create database XXX,来显示创建数据库的时候的编码设置. 一般 ...