• 野指针.

  • C语言: 当我们声明1个指针变量,没有为这个指针变量赋初始值.这个指针变量的值是1个垃圾指 指向1块随机的内存空间。
  • OC语言: 指针指向的对象已经被回收掉了.这个指针就叫做野指针.

  • 僵尸对象 
      一个OC对象引用计数为0被释放后就变成僵尸对象了,僵尸对象的内存已经被系统回收,虽然可能该对象还存在,数据依然在内存中,但僵尸对象已经是不稳定对象了,不可以再访问或者使用,它的内存是随时可能被别的对象申请而占用的
  • . 内存回收的本质.
  • 申请1块空间,实际上是向系统申请1块别人不再使用的空间.
  • 释放1块空间,指的是占用的空间不再使用,这个时候系统可以分配给别人去使用.
  • 在这个个空间分配给别人之前 数据还是存在的.
  • OC对象释放以后,表示OC对象占用的空间可以分配给别人.
  • 但是再分配给别人之前 这个空间仍然存在 对象的数据仍然存在.
  • 僵尸对象: 1个已经被释放的对象 就叫做僵尸对象.
      • . 使用野指针访问僵尸对象.有的时候会出问题报错(EXC_BAD_ACCESS),有的时候不会出问题.

        • 当野指针指向的僵尸对象所占用的空间还没有分配给别人的时候,这个时候其实是可以访问的.因为对象的数据还在.
        • 当野指针指向的对象所占用的空间分配给了别人的时候 这个时候访问就会出问题. 所以,你不要通过1个野指针去访问1个僵尸对象.

          • 虽然可以通过野指针去访问已经被释放的对象,但是我们不允许这么做.
      • . 僵尸对象检测.

        • 默认情况下. Xcode不会去检测指针指向的对象是否为1个僵尸对象. 能访问就访问 不能访问就报错.
        • 可以开启Xcode的僵尸对象检测. 
          • 那么就会在通过指针访问对象的时候,检测这个对象是否为1个僵尸对象 如果是僵尸对象 就会报错.
      • . 为什么不默认开启僵尸对象检测呢?

        • 因为一旦开启,每次通过指针访问对象的时候.都会去检查指针指向的对象是否为僵尸对象.
        • 那么这样的话 就影响效率了.
  • . 如何避免僵尸对象报错. 
      • 当1个指针变为野指针以后. 就把这个指针的值设置为nil
  • 僵尸对象无法复活.
      • 当1个对象的引用计数器变为0以后 这个对象就被释放了.
      • 就无法取操作这个僵尸对象了. 所有对这个对象的操作都是无效的.

      • 因为一旦对象被回收 对象就是1个僵尸对象 而访问1个僵尸对象 是没有意义.


  • 空指针 

    空指针是指没有指向任何东西的指针(存储的东西是nil、NULL、0),给空指针发送消息不会报错


开启Xcode对僵尸对象检测调试

BAD_ACCESS 在什么情况下出现

BAD_ACCESS 报错属于内存访问错误,会导致程序崩溃,错误的原因是访问了野指针(悬挂指针)。野指针指的是本来指针指向的对象已经释放了,但指向该对象的指针没有置 nil,指针指向随机的未知的内存,程序还以为该指针指向那个对象,导致存在一些潜在的危险访问操作,这些危险访问操作无法被指针指向的未知内存所处理,就会导致BAD_ACCESS错误造成程序崩溃。访问的含义包括多种情况,例如:向野指针发送消息,读写野指针本来指向的对象的成员变量等等。

如何调试BAD_ACCESS错误

首先调试BAD_ACCESS错误是比较困难的,我们知道BAD_ACCESS错误是由于访问了野指针,但程序不会在野指针出现时或者在我们访问野指针的代码处报错,导致对其难以察觉,调试方法思路如下:

  • 开启僵尸对象诊断

首先是开启僵尸对象诊断模式,利用僵尸对象来对野指针的出现位置提供线索。我们知道僵尸对象指的是引用计数为0被系统回收的对象,但这些对象暂时还存在于内存中,且理论上还是可以使用的,但是不稳定。开启僵尸对象诊断后,僵尸对象会暂时保持活跃用于调试,我们的野指针在对象回收后依然指向该僵尸对象,在访问野指针也就是访问僵尸对象的情况下可以被编辑器检测出来。这个时候还是会报BAD_ACCESS错误,但是后台会打印出该线索,例如下面的访问野指针打印的后台信息:

 

可以看出Xcode告诉我们消息发送给了一个僵尸对象,僵尸对象原本是一个实例,但现在该对象被回收了而开发者还试图访问它,由此可以很容易定位问题所在。

另外开启僵尸对象诊断的方法为:打开Xcode顶部导航栏的Product-Scheme-Edit Scheme,在弹出的界面中选中左侧的Run模式,然后勾选右侧Dianostics下的Zombie Objects。

为什么不默认开启僵尸对象检测呢?

因为一旦开启,每次通过指针访问对象的时候,都会去检查指针指向的对象是否为僵尸对象。所以会影响程序的执行效率,建议关闭。

  • Analyze分析

僵尸对象诊断可以帮助快速定位多数情况下的野指针问题,但也有时候不能奏效,这个时候只能利用Xcode的Analyze静态分析帮助检查可能出问题的地方,仔细检查问题所在,比较费时。

使用方法很简单,选中Xcode顶部导航栏Product-Analyze或使用快捷键Command+Shift+B,分析需要花一些时间,然后左侧会列出编辑器发现的存在潜在问题的地方,选中蓝色图标对应的问题项会跳到问题项所在的代码行。但这只能给出一些潜在提示,帮助搜索问题所在,不一定和我们的bug相关。

定位到问题后把野指针至nil

 
 

用心去理解

iOS-野指针与僵尸对象的更多相关文章

  1. OC中的野指针(僵尸指针)

    涉及到内存管理问题的都是类类型的变量,而在OC中我们操纵这些对象都是通过操纵指向他们的指针来完成的,一致很多时候会忽略指针存在.比如定义UIView * view = [[UIView alloc]i ...

  2. ios野指针的3种常见情况

  3. Objective-C 【单个对象内存管理(野指针&内存泄露)】

    ------------------------------------------- 单个对象内存管理 (1)野指针 ①定义了一个指针变量,但是并没有赋初值,它随机指向一个东西 ②某指针变量指向的内 ...

  4. OC-引用计数器,内存管理,野指针

    总结 全局断点 →-->+-->Add Exception Breakpoint 开启僵尸监听 打开Edit scheme -->Diagnostics-->Enable Zo ...

  5. 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理

    1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...

  6. iOS 关于僵尸对象和僵尸指针的那些事儿

    引言 提到僵尸就感到一种恐怖,大家都知道“僵尸”是没有生命的,但是它确实是一种存在的类似生命体的一种生物.哈哈,当然本文的重点不是讨论“僵尸”,而是有关于ios当中经常遇到的僵尸指针(Zombie P ...

  7. iOS中僵尸对象的实现方法

    什么是僵尸对象?所谓僵尸,就是过度释放的对象.在ios开发中,僵尸对象对于开发人员调试程序来说很有用.我们通常将NSZombieEnabled环境变量设置为YES来打开僵尸对象,但这会导致所有的对象都 ...

  8. iOS 类方法 、野指针与空指针

    一.类方法: 不依赖于对象,执行效率更高; 能用类方法解决的问题,尽量使用类方法; 类方法中不能直接访问实例变量(成员变量) 二.野指针和空指针是什么?什么时候产生?怎么避免? 只要一个对象被释放了, ...

  9. iOS开发_内存泄漏、内存溢出和野指针之间的区别

    今天,在工作群中,被问到了内存泄漏和野指针指向的区别,自己答的不是很好,特意回来查了资料,在博文中总结一下经验,欢迎指正. 内存泄漏:是指在堆区,alloc 或new 创建了一个对象,但是并没有放到自 ...

随机推荐

  1. JS_高程5.引用类型(1)Object类型

    引用类型 在ECMASCript中,引用类型是一种数据结构,将数据和功能组织在一起,引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法.(注意:尽管ECMAScript从技术上 ...

  2. python部分面试- 测试维度

    2. 软件测试的维度 1. 正确性:功能 正确 2. 健壮性: 意外的输入,不会崩溃 3. 性能: 大压力, 依然能工作 4. 可靠性: 长时间,不会崩溃 5. 易用性: 目标客户,都易用 6. 安全 ...

  3. fzu1062 洗牌问题(思路模拟)

    http://acm.fzu.edu.cn/problem.php?pid=1062 一开始想暴力找规律,没看出来..然后开始推,推测根据1再次返回第一个的时候顺序也复原,然后想以此推导出一个规律公式 ...

  4. C# Xamarin For Android自动升级项目实战

    一.课程介绍 “明人不说暗话,跟着阿笨一起玩Xamarin”,本次分享课程阿笨将带来大家一起学习Xamarin For Android系列<C# Xamarin For Android自动升级项 ...

  5. 【不做标题党,只做纯干货】HashMap在jdk1.7和1.8中的实现

     同步首发:http://www.yuanrengu.com/index.php/20181106.html Java集合类的源码是深入学习Java非常好的素材,源码里很多优雅的写法和思路,会让人叹为 ...

  6. 使用AShot进行网页全页截图

    import org.junit.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.Chrom ...

  7. shell编程学习笔记(五):Shell中脚本的参数

    在执行Shell脚本的时候,可以在执行时带上参数,相当于传递参数给脚本,下面我们看一下怎么使用这个参数 以下蓝色字体部分为Linux命令,红色字体的内容为输出的内容: # cd /opt/script ...

  8. SpringBoot之整合Redis分析和实现-基于Spring Boot2.0.2版本

    背景介绍 公司最近的新项目在进行技术框架升级,基于的Spring Boot的版本是2.0.2,整合Redis数据库.网上基于2.X版本的整个Redis少之又少,中间踩了不少坑,特此把整合过程记录,以供 ...

  9. 【php】php输出jquery的轮询,5秒跳转指定url

    1.在php中直接输出jquery的轮询,5秒后跳转指定url 2.代码稍微改动,即可在html中使用 3.代码: public function alpha(){ $html = '<!DOC ...

  10. python - Linux C调用Python 函数

    1.Python脚本,名称为py_add.py def add(a=,b=): print('Function of python called!') print('a = ',a) print('b ...