Object-c 内存一些事
1 @interface ClassC : NSObject {
2 @private
3
4 }
5 @end
6
7 @implementation ClassC
8
9 -(void) dealloc
10 {
11 [super dealloc];
12
13 }
14 @end
15
16 @interface ClassB : NSObject {
17 @private
18 ClassC * class_c;
19 }
20
21 @property(nonatomic, retain) ClassC * classc;
22 @end
23
24 @implementation ClassB
25
26 @synthesize classc = class_c;
27 -(id) init
28 {
29 if (self = [super init]) {
30 class_c = [[ClassC alloc] init];
31 }
32
33 return self;
34 }
35
36 -(void) dealloc
37 {
38 [super dealloc];
39 self.classc = Nil;
40 // [class_c release];
41 }
42 @end
调用如下:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ClassB * b = [[ClassB alloc] init]; [b release]; [pool release]; }
根据调试的结果,在ClassB的dealloc中使用:self.classc = Nil;也可以执行到ClassC的dealloc方法, 说明使用self.classc = Nil & self.classc = nil & [class_c release]的效果都是一样的。
如果在ClassB的init方法不去初始化 class_c 执行[class_c release] 也不会出错,因为ios中向一个空的对象发送消息是没有问题的。
在ClaasB中
-(void) dealloc { [super dealloc]; // self.classc = nil; [class_c release]; // class_c = nil; [class_c release]; class_c = nil; }
也不会有问题。
但是,在ClassB中如下就出问题了
@interface ClassB : NSObject { @private ClassC * class_c; ClassC * class_c1; ClassC * class_c2; } @property(nonatomic, retain) ClassC * classc; @property(nonatomic, retain) ClassC * classc1; @property(nonatomic, retain) ClassC * classc2; -(void) test; @end @implementation ClassB @synthesize classc = class_c; @synthesize classc1 = class_c1; @synthesize classc2 = class_c2; -(id) init { if (self = [super init]) { class_c = [[ClassC alloc] init]; class_c1 = [[ClassC alloc] init]; class_c2 = [[ClassC alloc] init]; } return self; } -(void) test { self.classc = self.classc1; self.classc1 = self.classc2; self.classc2 = nil; } -(void) dealloc { [super dealloc]; self.classc = Nil; // = nil 也是一样的 self.classc1 = Nil; self.classc2 = Nil; // [class_c release]; // class_c = nil; // // [class_c1 release]; // class_c1 = nil; // // [class_c2 release]; // class_c2 = nil; } @end
这样在[b release];的时候 就报了 EXC_BAD_ACCESS错误, 好换种写法:
-(void) dealloc { [super dealloc]; // self.classc = nil; // self.classc1 = nil; // self.classc2 = nil; [class_c release]; class_c = nil; [class_c1 release]; class_c1 = nil; [class_c2 release]; class_c2 = nil; }
这次就正确了,没有任何错误,得到结论1:在释放对象的时候,使用 [xxx release]; 尽量不要使用self.xxxx = nil这种方式。
此时多调用 几次
[b test];
[b test];
[b test];
[b test];
也没有错误, 再试下不初始化 三个class_c 也是没有问题的。
但是:我们之前也有得到一个结论:说明使用self.classc = Nil & self.classc = nil & [class_c release]的效果都是一样的。
那这两个结论不是矛盾的么? 其中的原因到底是为什么?我接着做了如下尝试:
@interface ClassB : NSObject { @private ClassC * class_c; ClassC * class_c1; ClassC * class_c2; } @property(nonatomic, retain) ClassC * classc; @property(nonatomic, retain) ClassC * classc1; @property(nonatomic, retain) ClassC * classc2; -(void) test; @end @implementation ClassB @synthesize classc = class_c; @synthesize classc1 = class_c1; @synthesize classc2 = class_c2; -(id) init { if (self = [super init]) { class_c = [[ClassC alloc] init]; class_c1 = [[ClassC alloc] init]; class_c2 = [[ClassC alloc] init]; } return self; } -(void) test { NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc = self.classc1; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc1 = self.classc2; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc2 = nil; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); } -(void) dealloc { [super dealloc]; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc = nil; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc1 = nil; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc2 = nil; // [class_c release]; // class_c = nil; // // [class_c1 release]; // class_c1 = nil; // // [class_c2 release]; // class_c2 = nil; }
这样结果也是一样的,很崩溃,在ClassB的dealloc方法里面,没关系再试试,我重新尝试了一下
-(void) dealloc { NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc = nil; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc1 = nil; NSLog(@"class_c is :%d", class_c.retainCount); NSLog(@"class_c1 is :%d", class_c1.retainCount); NSLog(@"class_c2 is :%d", class_c2.retainCount); self.classc2 = nil; [super dealloc]; }
这时候竟然神一样的没有问题了, 不同的地方就是[ super dealloc ] 这句,放到后面就正确了,再做如下两个实验:
-(void) dealloc { [class_c release]; class_c = nil; [class_c1 release]; class_c1 = nil; [class_c2 release]; class_c2 = nil; [super dealloc]; }
-(void) dealloc { [super dealloc]; [class_c release]; class_c = nil; [class_c1 release]; class_c1 = nil; [class_c2 release]; class_c2 = nil; }
这两种都是可以正确执行的,没有问题,那么问题的核心就在 [super delloc] 到底对 sekf.xxxx = nil 有什么影响?
作者:GangWang
出处:http://www.cnblogs.com/GnagWang/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。