开发者

Potential leak of an object warning -- clarification needed

After I Analyzed my code, Xcode indicated a potential leak as shown below.

Potential leak of an object warning -- clarification needed

Is this something I should be concerned about?

In this code, the class that sets doublyLinkedList is the sole owner and continues to开发者_StackOverflow manage this object throughout program execution.


The reason you're getting the warning is because the new call returns a retained object, and then your setter is probably doing another retain on it (depends on whether it's synthesized or manually generated).

Also, I would recommend you use the standard alloc/init instead of new, so that the two-phase creation is obvious.

This is better:

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

or just

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


You may wish to do this instead:

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

In the header, declare doublyLinkedList a @property that is retained.


You have a "potential leak" because the Analyzer sees that you have allocated memory for a DoublyLinkedList instance (using new), put it into a local variable called dll, and not released that memory in the same scope.

Assuming that the doublyLinkedList member that you're setting happens to also be a property declared as retaining, you also have an actual leak, because you have over-retained the DoublyLinkedList that you create here.

The ownership rules say that you have one claim on this instance because you called new to create it. When you pass the instance to setDoublyLinkedList:, it is retained, and you then have two claims. When the init method ends, you only have one reference to the instance, through the ivar/property -- you've lost the local variable -- which means that you have more ownership claims than you have references. This is a good indication that you will have a leak.

To fix the leak, you need to relinquish one of your claims before the end of the init method. You can do this in one of two ways, using release as soon as the property is set:

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

or autorelease:

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

However, it should be noted that using setters in init may be problematic (see also Mike Ash's writeup on the topic), because accessors can -- potentially -- have side effects that depend on your object already being fully set up. There seem to be two camps on this issue, and it's probably best to read about it and come to your own conclusions, but you may find that it simplifies your initializer methods to assign to ivars rather than using properties:

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

This is completely correct in terms of memory management.

Finally, if DoublyLinkedList is a class whose code you have, you can also consider writing a convenience constructor, which will return a new, autoreleased instance for you. The convention in Cocoa is to simply name the method after the class, with standard method name casing, like so:

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

Note that this is a class method:

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

and see my answer to "Self-allocating objects" for an explanation of these constructors.


If you have a property called "doublyLinkedList" (assumption based on code given), and it is "retained," you can do the following:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜