格而知之4:寻找EXC_BAD_ACCESS
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的更多相关文章
- 格而知之3:Core Data的基本使用
最近准备做一个随手笔记类的app给自己用,考虑到从未使用过Core Data,就决定用Core Data来做数据存储.在网上参考了一些Core Data的资料后,用一天的时间写了这个demo,主要测试 ...
- 格而知之16:我所理解的Block(3)
23.在前文中的例子中,Block结构体里的isa指针还没有详细讲解,这个指针都被置向了_NSConcreteStackBlock,它标识了Block的类型. 其实除了_NSConcreteStack ...
- 格而知之16:我所理解的Block(2)
11.那么Block到底是怎么实现的呢?试一试通过将Block 的代码转换成普通C语言代码来查看它的实现过程. 要将OC代码转换成C语言代码,可以使用clang编译的一个命令: 通过这个命令能把指定文 ...
- 格而知之15:我所理解的Block(1)
1.Block 本质上是一个struct结构体,在这个结构体中,最重要的成员是一个函数(当然除函数外还有其他重要的成员). 2.在开始解析Block之前,首先来回顾一下Block的格式.Block相关 ...
- 格而知之9:一些关于GCD的笔记
1.最近在重读当年刚开始学习多线程时的笔记,发觉其中有一些地方还是比较容易模糊,于是整理这篇笔记记录一下. 执行方式和队列 2.队列用来存放管理要执行的任务,它分为并发队列(Concurrent Di ...
- 格而知之8:我所理解的Runtime(3)
关联对象 14.使用Category对类进行拓展的时候,只能添加方法,而不适合添加属性(可以添加属性,也可以正常使用get方法和set方法,只是不会自动生成以下划线开头命名的成员变量). 可以通过关联 ...
- 格而知之7:我所理解的Runtime(2)
消息发送(Messaging) 8.以上便是runtime相关的一些数据结构,接下来我们回看一开始的疑问: objc_msgSend()函数在执行的过程中是如何找到对应的类,找到对应的方法实现的呢? ...
- 格而知之6:我所理解的Runtime(1)
基本简介 1.根据官方文档,OC有一个特性:它会尽可能把一些决定从编译时和链接时推迟到运行时才处理,所以这门语言需要的就不只是一个编译器,它还需要一个runtime系统来处理那些已经被编译过的代码. ...
- 格而知之5:我所理解的Run Loop
1.什么是Run Loop? (1).Run Loop是线程的一项基础配备,它的主要作用是来让某一条线程在有任务的时候工作.没有任务的时候休眠. (2).线程和 Run Loop 之间的关系是一一对应 ...
随机推荐
- 要理解javascript中间apply和call
apply和call它是javascript一个非常重要的方法,.虽然与程序平时很少接触,但JS到处都在使用这个框架2方法. 2个方法是在Function.prototype中.也就是说每一个JS函数 ...
- js获取名字为XX的标签
$("input[name='XX']"); <input name="address_select" type="radio" va ...
- ASP.NET导入Excel到SQL数据库
protected void btnChange_Click(object sender, EventArgs e) { UserInfoClass tClass = (UserInfoClass)S ...
- 配置元素customErrors
Asp.net配置文件的配置方式,其实在MSDN里面是写得最清楚的了.可惜之前一直未曾了解到MSDN的强大. 先贴个地址:http://msdn.microsoft.com/zh-cn/library ...
- 原创:C sharp 中 Enum的几点小 Tips
(1)为什么要使用Enum? ♥ enums枚举是值类型,数据直接存储在栈中,而不是使用引用和真实数据的隔离方式来存储.enum student{a,b,c,d,e},其中enum代表student为 ...
- javascript延迟加载及异步(defer和async)
一直以来写代码的时候的常用习惯就是吧所有的js文件直接加载在文档的head标签里面,在写js文件的时候有时候获取一些文件对象的时候为空对象,这是由于文档结构还没有加载完,但是js文件已经加载完.也就是 ...
- Qt通过odbc读取excel数据
传统的读取方式是通过Excel.Application,这种方式不仅操作繁琐,而且速度也不快. 通过odbc读取,可以使用select语句直接读取整个工作表,处理excel数据就跟数据库一样方便. 当 ...
- VLC的相关文档以及javascript接口
参看下面链接:VLC相关文档
- Qt之等待提示框三(QLabel进行多图片切换)
之前分享过的等待提示框有用QMovie播放gif图片实现的,也有纯代码实现的,今天再次分享另一种实现方式,如题目所示:QLabel进行图片的切换! 进行用户登录的时候,往往都需要后台线程进行用 ...
- 解决MySQL中文乱码的问题
遇到中文乱码问题,首先用status命令检查数据库的配置,如下: 上图会显示数据库配置的各项信息. 还可以用 show create database XXX,来显示创建数据库的时候的编码设置. 一般 ...