黑马程序员技术交流社区
标题:
关于在dealloc里面设置sefl = nil
[打印本页]
作者:
汪坤洋
时间:
2015-11-9 00:41
标题:
关于在dealloc里面设置sefl = nil
今天一个同学问我一个问题,感觉很有意思,分享出来给大家,也感谢这位同学让我学到不少东西
问题的主要点就是 在dealloc里面设置sefl = nil
main 函数
Car *car1 = [Car new];
car1.speed = 280;
car1.name = @"君越";
[fengjie setCar:car1];
NSLog(@"%lu",[car1 retainCount]);
Car * car2 = [Car new];
car2.speed = 350;
car2.name = @"宝马";
[fengjie setCar:car2];
[fengjie goLasa];
NSLog(@"%lu",[car1 retainCount]);
NSLog(@"%@",car1);
[car1 release];
//[car1 release];
NSLog(@"%@",car1);
//car1 = nil;//在这边调用car1赋值为nil能成功是因为car1是栈区里的变量,而堆区的对象已经释放了。下面35行重新设置[fengjie setCar:car1]就不行了。但是在car自己的dealloc里面设置sefl = nil;却能重新调用car堆内的对象,为什么?而且僵尸对象检测不到car1。
/*
在car自己的dealloc里面设置sefl = nil
使释放内存的方法失效了 如果你在 [super dealloc] 后面写就会报僵尸对象 或者重新调用一下[super dealloc] 方法也会报僵尸对象
这个问题最根本的原因有两点
1、self存在作用域 出了dealloc方法后又会重新指向对象
2、对象释放 其实是在父类方法里面执行的
关于self作用域问题 在对象方法中self 就是一个对象 但是其本质应该是一个指针 谁调用的 就指向谁 一个存储对象地址的指针 把self=nil只是把这个指针指向了空 但是不会影响我们在外面创建的对象
以后千万不要在dealloc方法里面写 sefl = nil
*/
//释放失败,在这里继续调用也会成功
[car1 ssss];
//NSLog(@"%@",car1);
//[car1 release];
NSLog(@"%lu",[car1 retainCount]);
[fengjie setCar:car1];
//[fengjie release];
[fengjie goLasa];
[fengjie goLasa];
car代码
- (void) dealloc {
NSLog(@"1----%@",self);
self = nil; //这样写会造成内存泄漏
NSLog(@"2----%@",self);
//释放对象内存应该写在父类的方法中 提前把self指向空 父类释放对象就会失败 self 应该也是有作用域的
[super dealloc];
}
-(void)ssss{
NSLog(@"3----%@",self);
[super dealloc];
}
作者:
汪坤洋
时间:
2015-11-9 00:44
以上是主要代码,不太会编辑,大家将就看吧
作者:
向日葵的微笑
时间:
2015-11-9 00:46
赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞
作者:
wx_xO9vSwPo
时间:
2015-11-9 01:09
牛,赞赞赞赞
作者:
许本亮
时间:
2015-11-9 08:55
受教了,顶一下
作者:
Windnon
时间:
2015-11-9 22:09
不明觉厉~~~~~~~~~~~~
作者:
liuch111
时间:
2015-11-9 23:16
还好我看过 xcode版 源码... 不然 "大神" 贴出来的代码能把人看晕
不过还是谢谢分享,,
作者:
汪坤洋
时间:
2015-11-10 15:15
整理之后的
问题
在car自己的dealloc里面设置sefl = nil。
解决过程:
主要的类和分析见下面
main方法
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *fengjie = [Person new];
Car *car1 = [Car new];
car1.speed = 280;
car1.name = @"君越";
[fengjie setCar:car1];//这时候car1 计数器为2
NSLog(@"%lu",[car1 retainCount]);
[car1 release];//这时候car1 计数器为1
NSLog(@"%lu",[car1 retainCount]);
[car1 release];//这时候car1 计数器为0 调用dealloc方法(方法见car.m文件)
NSLog(@"%lu",[car1 retainCount]);//正常结果应该报僵尸错误 但是在 dealloc里面设置sefl = nil 使对象释放失败 这时候返回计数器为 1
//在发下一条消息前 self是指向nil的
Car *susu = [car1 self];
[car1 release];//继续 release 但是这时候对象不会继续自动调用 dealloc 但是计数器返回的数字很奇怪
NSLog(@"%lu",[car1 retainCount]);// 返回 4611686018427387904
NSLog(@"%d",[car1 retainCount]);// 返回 0
//如果重新调用父类的dealloc方法 对象还是可以被释放的 说明释放对象的方法是写在nsobject的dealloc方法里
//[car1 ssss];
//这时候car1 被释放了 继续调用就会报错
//NSLog(@"%@",car1);
[fengjie release];
/*
这个问题最根本的原因有两点
1、self存在作用域 出了dealloc方法后又会重新指向对象(针对这点 后面有详细解释)
2、对象释放 其实是在父类方法里面执行的
结论
以后千万不要在dealloc方法里面写 sefl = nil 这样会造成内存泄漏
引发的其他问题
释放失败之后的计数器 结果是1 当再次 release后 计数器的结果在%lu上是一个很大的数字 在%d中是0
self究竟是什么,详情请见《oc加强2》
*/
}
return 0;
}
Car.m
#import "Car.h"
@implementation Car
- (void)run{
NSLog(@"%@以%d的速度向前奔跑",_name,_speed);
}
- (void) dealloc {
NSLog(@"1----%p",&self);
self = nil; //这样写会造成内存泄漏
NSLog(@"2----%p",&self);
//释放对象内存应该写在父类的方法中 提前把self指向空 父类释放对象就会失败 self 应该也是有作用域的
[super dealloc];
}
-(void)ssss{
NSLog(@"3----%@",self);
[super dealloc];
}
@end
结论
以后千万不要在dealloc方法里面写 sefl = nil 这样会造成内存泄漏 也不要漏写[super dealloc]正真释放内存的方法就在这里
引发的其他问题
释放失败之后的计数器 结果是1 当再次 release后 计数器的结果是一个很大的数字
self究竟是什么,详情请见《oc加强2》
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2