以下是我在运行以下代码时看到的内容:
// Dealloc on MyClass not called
MyClass* c = [MyClass new];
self.a = [NSMutableArray new];
[self.a addObject:c];
[c release];
[a release];
// Dealloc on MyClass called
MyClass* c2 = [MyClass new];
NSMutableArray* a2 = [NSMutableArray new];
[a2 addObject:c2];
[c2 release];
[a2 release];
// Dealloc on MyClass called
MyClass* c3 = [MyClass new];
a = [NSMutableArray new];
[a addObject:c3];
[c3 release];
[a release];
为什么在第一个例子中没有调用dealloc?
编辑:
我想我误解了这一切。基本上我需要做的是:
NSMutableArray* alocal = [NSMutableArray new]; // alocal has a retain count of 1
self.a = alocal; // a has a retain count of 1
[alocal release]; // alocal has a retain count of 0
[a release]; // a has a retain count of 0
OR
self.a = [[NSMutableArray new] autorelease]; // a has a retain count of 2
[a release]; // a has a retain count of 0
OR
self.a = [NSMutableArray array]; // a has a retain count of 2
[a release]; // a has a retain count of 0
就像注释一样,使用自动释放/数组选项(#2和#3),a不会立即释放,所以如果你想要更多的控制,请选择#1。
谢谢!
答案 0 :(得分:3)
因为在第一个示例中,假设a
是保留/复制属性,则数组会泄漏。
self.a = [NSMutableArray new];
顺便说一句,它与第三个例子不同:
a = [NSMutableArray new];
在第三种情况下,对象直接分配给ivar(不涉及属性设置器)。
回到第一个例子,方法new
返回一个保留对象(+1),然后属性setter也保留对象(+2)。然后,当释放属性(-1)时,最终得到+1。这是错的。您需要平衡您的保留/发布以最终得+0。
一个简单的解决方案是使用便利构造函数:
self.a = [NSMutableArray array];
在这种情况下,方法array
返回一个自动释放的对象(+0),属性setter保留对象(+1),它由属性的释放(-1)平衡,你结束用+0。
此外,在第一个示例中,您通过ivar:
释放您设置为属性的对象[a release];
结果,该属性现在持有一个指向可能已释放的对象的指针。由于您放弃了对象的所有权,因此无法保证该对象将来会存活。如果该对象实际上已被释放(因为它没有任何其他所有者),您的指针仍将指向该对象过去所在的堆中的内存地址;除了现在,该地址可能包含任何内容:所述对象的旧位模式,或不相关的对象,或绝对垃圾。
如果您向解除分配的对象发送消息,例如,没有任何好处,例如它会让你的应用程序崩溃。要避免这种情况,请通过属性释放对象:
self.a = nil;
答案 1 :(得分:0)
这取决于你如何实施属性'a' 它应该是:
@property (retain) NSMutableArray *a;
当使用'new'时,它正在进行分配,所以你应该像这样自动释放它:
self.a = [[NSMutableArray new] autorelease];