【问题标题】:objective-c over-releasing in dealloc目标c在dealloc中过度释放
【发布时间】:2010-05-23 04:13:23
【问题描述】:

mystring 是否过度释放?

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

我认为这不会基于 [nil release] 什么都不做:

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

-编辑- 假设我在 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?
}

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

如果我在 doSomething 中明确设置为 nil,我是否可以在基于 dealloc 的情况下发布任意数量的版本?

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

【问题讨论】:

  • 取决于您通过复制或分配等方式增加了保留计数的次数。如果你从不以任何方式分配它,即使释放它一次也太多了。如果没有更多代码,您可能不会得到任何体面的答案
  • 好吧,看起来确实有点主观。但是,我的主要观点是我想不惜一切代价避免过度释放。我将添加另一个代码示例,让大家更好地了解我在整个代码中所做的工作。
  • 好的,基于我的第二个示例是正确的,我上面的附加代码示例如何适应过度发布?是否明确设置为零强制?
  • 我问这个的原因是我可以避免在 dealloc 中这样做: if (mystring) [mystring release];将 if (variable) 放置在任何地方都会变得啰嗦。

标签: iphone objective-c cocoa-touch


【解决方案1】:

对于您的第一个示例,答案可能是!

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

像这样过度释放有两个风险:

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

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

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

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

【讨论】:

  • 感谢您的解释,看来 obj-c 应该明确地将 dealloc 的对象设置为 nil 以避免这种在 dealloc 方法中过度释放的行为。也许有一些更好的理由不这样做。
【解决方案2】:

这完全取决于您保留 mystring 的次数。如果您有两个成员可能引用同一个对象并且都保留该对象,则它们都应该释放该对象。

因此,如果您使用 mystring = [[somestring retain] retain];

,您的第一个示例将是正确的

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-22
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      相关资源
      最近更新 更多