【问题标题】:Potential leak of an object warning -- clarification needed对象警告的潜在泄漏 - 需要澄清
【发布时间】:2011-11-30 03:37:01
【问题描述】:

在我分析了我的代码后,Xcode 指出了潜在的泄漏,如下所示。

这是我应该关心的事情吗?

在此代码中,设置doublyLinkedList 的类是唯一所有者,并在整个程序执行过程中继续管理此对象。

【问题讨论】:

  • 在下面的dealloc,我有[[self doublyLinkedList] release]

标签: objective-c xcode memory-management memory-leaks


【解决方案1】:

您收到警告的原因是因为 new 调用返回了一个保留对象,然后您的 setter 可能正在对它执行另一个 retain(取决于它是合成的还是手动生成的)。

另外,我建议你使用标准的alloc/init而不是new,这样两阶段的创建就很明显了。

这样更好:

if (self) {
    DoublyLinkedList *dll = [[[DoublyLinkedList alloc] init] autorelease];
    self.doublyLinkedList = dll;
}

或者只是

if (self) {
    self.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease];
}

【讨论】:

    【解决方案2】:

    您可能希望这样做:

    if (self) {
        DoublyLinkedList *dll = [DoublyLinkedList new];
        self.doublyLinkedList = dll;
        [dll release];
    }
    

    在标头中,声明一个被保留的@property doublyLinkedList。

    【讨论】:

    • 如果你分配[self setDoublyLinkedList:[DoublyLinkedList new]];,那你会如何发布呢?在这种情况下应该是[self setDoublyLinkedList:[[DoublyLinkedList new]] autorelease];
    • 是的,在那里自动释放。但请确保将 doubleLinkedList 的 @property 设置为保留。
    • 始终编写代码以获得最佳可读性。如果这样做[self setDoublyLinkedList:[[DoublyLinkedList new]] autorelease];最适合你,那就这样吧。我喜欢将事情分解,以便下一个程序员可以轻松检查它们,或者如果我需要有关 StackOverflow 的帮助。
    【解决方案3】:

    您有一个“潜在泄漏”,因为分析器看到您已为 DoublyLinkedList 实例分配内存(使用 new),将其放入名为 dll 的局部变量中,并没有在范围相同。

    假设您设置的 doublyLinkedList 成员恰好也是声明为 retaining 的属性,那么您也有一个实际泄漏,因为您过度保留了 @您在此处创建的 987654330@。

    ownership rules 表示您对该实例有一个声明,因为您调用了 new 来创建它。当您将实例传递给setDoublyLinkedList: 时,它会被保留,然后您有两个声明。当init 方法结束时,您只有一个对实例的引用,通过 ivar/property - 您丢失了局部变量 - 这意味着您拥有的所有权声明比引用的要多。这是一个很好的迹象,表明您将有泄漏。

    要修复泄漏,您需要在 init 方法结束之前放弃您的一项声明。您可以通过以下两种方式之一执行此操作,在设置属性后立即使用release

    DoublyLinkedList * dll = [DoublyLinkedList new];
    [self setDoublyLinkedList:dll];
    [dll release];
    

    autorelease:

    [self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
    // Or equivalent procedures involving a temp variable
    

    但是,应该注意在init may be problematic 中使用setter(另请参见Mike Ash's writeup on the topic),因为访问器可能——潜在地——产生依赖于您的对象已经完全设置的副作用。在这个问题上似乎有两个阵营,最好阅读它并得出自己的结论,但您可能会发现它简化了您的初始化方法以分配给 ivars,而不是使用属性:

    if( self ){
        doublyLinkedList = [DoublyLinkedList new];
    }
    

    这在内存管理方面是完全正确的。

    最后,如果DoublyLinkedList 是您拥有其代码的类,您还可以考虑编写一个方便的构造函数,它将为您返回一个新的、自动释放的实例。 Cocoa 中的约定是在类之后简单地命名方法,使用标准的方法名称大小写,如下所示:

    + (id) doublyLinkedList {
        return [[[self alloc] init] autorelease];
    }
    

    注意这是一个类方法:

    if( self ){
        [self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
    }
    

    有关这些构造函数的说明,请参阅 my answer to "Self-allocating objects"

    【讨论】:

      【解决方案4】:

      如果您有一个名为“doublyLinkedList”的属性(基于给定代码的假设),并且它是“保留的”,您可以执行以下操作:

      if (self) {
          DoublyLinkedList *dll = [[DoublyLinkedList alloc] init]
          self.doublyLinkedList = dll;
          [dll release];
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-06
        • 2012-01-17
        • 1970-01-01
        • 1970-01-01
        • 2016-09-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多