zoukankan      html  css  js  c++  java
  • 格而知之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的时候,都应该先判断一下是否为空。

  • 相关阅读:
    Unity项目
    Unity基本操作
    博客园自定义主题样式
    明解C语言
    C指针基础知识
    排序算法
    session理解与总结【session原理、应用、与cookie区别】
    cookie理解与实践【实现简单登录以及自动登录功能】
    【数据结构与算法】双指针思想——数组首部或尾部同向遍历
    【数据结构与算法】双指针思想——首尾双向遍历
  • 原文地址:https://www.cnblogs.com/shayneyeorg/p/5334310.html
Copyright © 2011-2022 走看看