在dealloc中,objective-c过度释放

时间:2010-05-23 04:13:23

标签: iphone objective-c cocoa-touch

mystring是否被过度释放?

-(void)dealloc {
    [mystring release];
    [mystring release];
    [super dealloc];
}

我认为这不会基于[nil release]不做任何事情:

-(void)dealloc {
    [mystring release];
    mystring = nil;
    [mystring release];
    [super dealloc];
}

CNC中 假设我在init中分配mystring并在doSomething中释放它:

-(id)init {
    if (self = [super init]) {
        mystring = [[NSString string] retain];
    }
    return self;
}
-(void)doSomething {
    [mystring release]; // for some good reason
    // ...etc
}

现在为了避免基于我上面的例子在dealloc中过度释放,我是否必须在doSomething方法中明确地执行此操作?

-(void)doSomething {
    [mystring release];
    mystring = nil; // <- is this mandatory to avoid over-releasing in dealloc?
}

最大的问题是,当我在类中的其他地方发布它时,我必须明确地将它设置为nil,以避免在dealloc中过度释放吗?

如果我在doSomething中明确设置为nil,那么我可以在dealloc中执行尽可能多的发布吗?

-(void)dealloc {
    [mystring release];
    [mystring release]; // <- does nothing because mystring explicitly nil?
}

3 个答案:

答案 0 :(得分:1)

对于你的第一个例子,答案可能是!

通常,每个持有对另一个对象的引用的对象应该保留它直到它们完成,然后调用一次释放,但是在一些非常奇特的(并且通常写得不好)的情况下,这可能不成立。如果将对象保留x次,则需要释放x次,以及其他内存管理不良的情况。但是最佳实践,是的,一个保留,一个发布,不会释放超过你保留的数量!

过度释放有两种风险:

第一个是如果第一个释放调用使得mystring的引用计数等于0,它将被释放,然后你将一条消息发送到一块不再是有效对象的内存。 Objective-C并不是真的喜欢这个,并且可能以各种方式做出反应,包括CRASHING。发送消息给nil,kosher,消息到dealloc'd,而不是那么多。

第二个是如果引用计数不为零,你刚刚发布了别人的引用,所以在将来的某个时候,一个引用mystring的对象可能会认为引用是有效的,它不会是因为当refcount在随后的释放调用中达到零时,它被释放。这比前一个错误更难检测,其中调试器至少会向您显示问题源自堆栈帧跟踪的实际区域。

你的第二个例子是正确的 - 向nil发送消息什么都不做。如果你担心你会做这样的事情,请确保在释放后将变量设置为nil。

编辑:是的。如果您打算在多个地方发布,那么您应该这样做,但是根据应用程序的不同,您可以考虑使用自动发布池。

答案 1 :(得分:0)

这一切都取决于你保留mystring的时间。如果你有两个成员可以引用同一个对象并且都保留对象,那么它们都应该释放该对象。

所以如果你使用mystring = [[somestring retain] retain],你的第一个例子就是正确的;

答案 2 :(得分:0)

第二个会更好。因为当你释放时,你释放mystring指向的内存而不是mystring的内存。因此, mystring不为空,如果有人意外使用它,您的应用将崩溃。它还取决于你的mystring被保留多少次