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. DirectX 初始化DirectX(第一方式)

      上一章我们学会了如何C++Win32项目中搭建DirectX开发环境, 那么下面来写代码初始化DirectX吧O(∩_∩)O~. 首先你创建一个Win32程序,点击运行你可以看见一个window窗 ...

  2. Android学习总结——本地广播机制

    为了简单解决广播的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能在程序的内部进行传递,只能接受来自本应用程序发出的广播.否则当我们发送一些携带关键数据的广播可能被截获,一 ...

  3. 关于使用STL常见的两个bug

    1.bug 1 class CTest { public : vector<int> getVector() const //需要写成引用形式,不然下面begin.end调用会以拷贝形式调 ...

  4. PHP <<EOF EOF的使用方法

    PHP <<EOF EOF的使用方法 <?php     $name = '浅水游';     print <<<EOT             <html& ...

  5. Unity 图片的灰度处理

    我们平时在做项目时,经常遇到按钮的点击而且还要区分悬浮,点击,禁用的状态,美术要针对一张图片做多个状态图片,资源图片的数量也就增大了,那么打出的包的大小也就跟着上去了,所以我们可以针对原始图片进行Sh ...

  6. Oracle 更改用户名

    直接更改系统user$表中的用户名. 查询要更改的用户名 SQL> select user#,name,password from user$ where name ='TICKETS'; US ...

  7. codeforces 336C Vasily the Bear and Sequence(贪心)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Vasily the Bear and Sequence Vasily the b ...

  8. (原+转)VS2013:正在从以下位置加载符号

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5158020.html 这段时间启动调试时,vs2013加载时间很长很长...然后下面网址给出了解决方法 ...

  9. Jquery网页选项卡应用

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  10. js验证身份证格式

    (function(){ Validate={ data:{ // 加权因子 Wi : [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 ...