物体警告的潜在泄漏 - 需要澄清

时间:2011-10-03 18:37:32

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

在我分析了我的代码之后,Xcode表明了潜在的泄漏,如下所示。 Screenshot of code with analysis results

这是我应该关注的吗?

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

4 个答案:

答案 0 :(得分:3)

您收到警告的原因是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];
}

答案 1 :(得分:1)

您可能希望这样做:

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

在标题中,声明doublelyLinkedList保留的@property

答案 2 :(得分:1)

您有“潜在泄漏”,因为分析器发现您已为DoublyLinkedList实例分配内存(使用new),将其放入名为dll的本地变量中,并且没有释放相同范围的内存。

假设您正在设置的doublyLinkedList成员也是声明为retain的属性,那么您还有实际泄漏,因为您已经结束 - 获取您在此处创建的DoublyLinkedList

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"以获取有关这些构造函数的说明。

答案 3 :(得分:0)

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

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