检测空指针 静态检测_iOS野指针,僵尸对象,空指针详解

一 野指针

C语言

当我们声明1个指针变量,没有为这个指针变量赋初始值.这个指针变量的值是1个垃圾指 指向1块随机的内存空间。

OC语言:

指针指向的对象已经被回收掉了.这个指针就叫做野指针。

二 僵尸对象

一个OC对象引用计数为0被释放后就变成僵尸对象了,僵尸对象的内存已经被系统回收,虽然可能该对象还存在,数据依然在内存中,但僵尸对象已经是不稳定对象了,不可以再访问或者使用,它的内存是随时可能被别的对象申请而占用的。

僵尸对象: 1个已经被释放的对象 就叫做僵尸对象.复制代码
1.内存回收的本质
  • 申请1块空间,实际上是向系统申请1块别人不再使用的空间.

  • 释放1块空间,指的是占用的空间不再使用,这个时候系统可以分配给别人去使用.

  • 在这个个空间分配给别人之前 数据还是存在的.

    • OC对象释放以后,表示OC对象占用的空间可以分配给别人.

    • 但是再分配给别人之前 这个空间仍然存在 对象的数据仍然存在.

2.使用野指针访问僵尸对象.有的时候会出问题报错(EXC_BAD_ACCESS),有的时候不会出问题.
  • 当野指针指向的僵尸对象所占用的空间还没有分配给别人的时候,这个时候其实是可以访问的.因为对象的数据还在.

  • 当野指针指向的对象所占用的空间分配给了别人的时候 这个时候访问就会出问题. 所以,你不要通过1个野指针去访问1个僵尸对象.

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

3.僵尸对象检测.

该功能的原理是,在对象释放(retainCount为0)时,使用一个内置的Zombie对象,替代原来被释放的对象。无论向该对象发送什么消息(函数调用),都会触发异常,抛出调试信息。

记得在问题被修复后,关闭该功能!!

记得在问题被修复后,关闭该功能!!

记得在问题被修复后,关闭该功能!!

  • 默认情况下. Xcode不会去检测指针指向的对象是否为1个僵尸对象. 能访问就访问 不能访问就报错.

  • 可以开启Xcode的僵尸对象检测.

    • 那么就会在通过指针访问对象的时候,检测这个对象是否为1个僵尸对象 如果是僵尸对象 就会报错.

4.为什么不默认开启僵尸对象检测呢?
  • 因为一旦开启,每次通过指针访问对象的时候.都会去检查指针指向的对象是否为僵尸对象.

  • 那么这样的话 就影响效率了.

5.如何避免僵尸对象报错.

当1个指针变为野指针以后. 就把这个指针的值设置为nil

6.僵尸对象无法复活.
  • 当1个对象的引用计数器变为0以后 这个对象就被释放了.

  • 就无法取操作这个僵尸对象了. 所有对这个对象的操作都是无效的.

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

三.空指针

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

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

4.1 BAD_ACCESS 在什么情况下出现

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

例如:

  • 向野指针发送消息

  • 读写野指针本来指向的对象的成员变量等等。

4.2 如何调试BAD_ACCESS错误

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

开启僵尸对象诊断

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

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

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

5c6b30a4236f76ddaf8c3e543de7c30b.png

25409dda1ec125d94bc5c1e68c27ba36.png

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

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

Analyze分析

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

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

58b8193454e6731be048f16afb30f4f6.png

扫描二维码

获取更多精彩

洲洲

e175e5e65655258515b17a9be39bc083.png ef7d001db74a99bf04470cdf62cafa24.gif

扫描上方二维码,关注我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值