一. 前言
最近最近被指派去解决一些线上的崩溃问题
,经常遇到野指针
导致的崩溃
。相对于其他的原因
引起的崩溃
来说,野指针
导致崩溃
是最难定位
的,这里主要总结了两种思路
来定位野指针
导致的崩溃。
二. 野指针
1.定义
当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称野指针.
2. 为什么Obj-C
野指针的Crash
那么多?
一般app
版本发布之前都会经过多轮研发自测
、测试内测
、灰度测试
、开放部分客户公测
等,按理说很多Crash
的场景都应该覆盖到了,但由于野指针
的随机性
,很经常会使得测试
的时候,它是没有问题,等到真正用户
使用的时候才有问题,
随机性
问题可以大概分为两类:
-
跑不进出错的逻辑,执行不到出错的代码,这种可以提高测试
场景覆盖度
来解决。 -
跑进了有问题的逻辑,但是
野指针
指向的地址并不一定会导致Crash
,这就有点看人品了?
为什么跑进了有问题
的逻辑
,但还是不一定会导致Crash
呢?
3.分析
野指针
是指指向一个已删除
的对象
或未申请
访问受限内存区域
的指针。本文说的Obj-C野指针
,说的是Obj-C对象
释放之后指针未置空,导致的野指针
(Obj-C
里面一般不会出现为初始化对象
的常识性错误)。
既然是访问已经释放的对象为什么不是必现Crash
呢?
因为dealloc
执行后只是告诉系统,这片内存我不用了,而系统并没有就让这片内存
不能访问。
现实大概是下面几种
可能的情况:
-
对象释放
后内存
没被改动过,原来的内存保存完好,可能不Crash
或者出现逻辑错误(随机Crash
)。 -
对象释放
后内存
没被改动过,但是它自己析构的时候已经删掉某些必要的东西,可能不Crash
、Crash
在访问依赖的对象
比如类成员上
、出现逻辑错误(随机Crash)
。 -
对象释放
后内存
被改动过,写上了不可访问
的数据
,直接就出错了很可能Crash
在objc_msgSend
上面(必现Crash
,常见)。 -
对象释放后
内存被改动过,写上了可以访问的数据,可能不Crash
、出现逻辑错误
、间接访问到不可访问的数据(随机Crash)
。 -
对象释放后
内存被改动过,写上了可以访问的数据,但是再次访问的时候执行的代码把别的数据写坏了,遇到这种Crash
只能哭了(随机Crash,难度大,概率低)
!! -
对象释放
后再次release
(几乎是必现Crash
,但也有例外,很常见)。
如图所示: