前言
野指针就像是代码中的炸弹,它的存在会导致很多隐患,因为不知道什么时候就会触发。在开发中经常会发生莫名其妙的crash,很多情况下就是野指针造成的。
- 野指针
野指针和空指针是不一样的,空指针没有储存任何的内存地址,而野指针指向的一块内存地址,但是该内存不可用。换句话说,野指针指向的对象已经被释放了。
Person *p =[[Person alloc]init];
[p setName:@"wang"];
[p release]; //指针p指向的对象已经被释放,但是该指针还能访问该内存地址
[p setName:@"zhao"]; //所以此处不会报错
但是这是存在隐患的,这种情况下被释放掉的对象就会成为僵尸对象。僵尸对象很可能会导致代码crash。
僵尸对象
在OC中,对象被释放后所占用的内存在没有被复写(重新分配给其他对象)前称为僵尸对象,这是野指针是可以访问该内存的,因为对象的数据还在,所以程序不会报错。但是该内存一旦重新分配给其他对象就会出现问题。-
检测僵尸对象
所以虽然可以通过野指针去访问已经被释放的对象,但是我们不允许这么做。
在编码的时候就要去检测僵尸对象。
这样在[person release]之后
person对象被释放了,由于scheme开启了僵尸对象选项,所以person对象在释放时调用的dealloc方法在底层被swizzle了
dealloc方法执行时,代码走的并不是清理资源,回收内存。而是copy了一个NSZombie对象模版,并修改zimbie对象的isa指针,形成了一个新的僵尸对象类_NSZombie_Person。所以在[person release];执行之后, 打印的person对象类型为_NSZombie_Person
_NSZombie_Person类中只有一个isa指针,里面没有其他的属性和方法,所以不能响应任何事件,所以在向这个僵尸对象发送消息时,就会报错,并打印出来。这非常有利于调试。
- 避免野指针
很简单,在realase之后将指针指向nil即可。
p = nil;
之后该指针就不能访问到僵尸对象了。
参考资料:一起来构建NSZombie