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的时候,都应该先判断一下是否为空。

  • 相关阅读:
    [Unity3D]计时器/Timer
    unity缓存和浏览器缓存
    unity3d进行脚本资源打包加载
    Unity3d删除无用的美术资源
    项目经理的职责(转载)
    LINQ
    生意经
    Android ListView标题置顶效果实现
    ListView的自动循环滚动显示
    郭霖的专栏
  • 原文地址:https://www.cnblogs.com/shayneyeorg/p/5334310.html
Copyright © 2011-2022 走看看