Is this an objective-c memory leak?


Is this an objective-c memory leak?



I know that if you do the following you most certainly have a memory leak:

id foo = [[NSObject alloc] init]; foo = nil; 

But, what if you're using self.foo, a property with retain? And your code instead looks like the following:

foo = [[NSObject alloc] init]; self.foo = nil; 

Is that still a memory leak since the accessor releases the memory first before setting it to nil?




Add to arrayController, edit Core Data attribute

1:



NSTextFieldCell Coordinates
self.foo = nil would translate into.
How do I convert NSString with Hexvalue to binary char*?
[nil retain] [foo release] foo = nil 
There is no memory leak here..
How would you make a Checkbox Cell only display on a Certain Entitys Rows in An Outline View?


What is the correct way to tell when an NSArrayController is finished loading its content from a persistent store?


Populating Object in Objective C

2:



Threading in Objective-C
Nope, the second example is not a memory leak.


Core Data NSPredicate for relationships
In fact, that's how I deal with retain properties in my dealloc method.

It's just a lot cleaner.. The only thing you have to be careful about is making sure not to write.
self.foo = [[NSObject alloc] init]; 
or else you'll double-retain the object and end up with a memory leak..


3:


Properties make it your code look like assignment, but in reality they're the same as traditional accessor methods you might have written yourself prior to Obj-C 2.0.

With properties Obj-C is simply generating the accessor methods behind the scenes for you instead using the keywords you specify in the declaration (assuming you use @synthesize and don't write your own accessor methods anyway)..


4:


No, there is no memory leak.

The code in your second example is logically equivalent to .
foo = [[NSObject alloc] init]; [nil retain]; [foo release]; foo = nil; 
because the @synthesized setter is logicall equivalent to .
- (void)setFoo:(id)newFoo {   [newFoo retain];   [foo release];   foo = newFoo; } 
It's worth noting that setting foo directly is probably not something you want to do outside of an init method.

If you assign a value to foo directly, you bypass the automatic KVO notification (you would have to wrap your assignment in a willChangeValueForKey:/didChangeValueForKey: pair) and you break any subclass' behavior if it overrides the setFoo: method, expecting all modifications of foo to go through the setter.. You assign directly to foo in an init method because the setFoo: method or a subclass' overriden setFoo: method may have side-effects or depend on the instance's fully initialized.. Similarly, you would use [foo release] rather than self.foo = nil; in the -dealloc method for the same reasons..


5:


All the answers so far assume that “foo” in the first line of the second example is the instance variable behind the foo property.

This is the default behavior.. If the foo that the first line assigns to is a local variable, then the foo property is irrelevant, and you will leak the object unless you release it later in the method.. If foo is an instance variable, but the foo property is actually backed by a different instance variable, or no instance variable at all, then (a) you are writing hard-to-maintain code and (b) it may be a leak.. Finally, echoing the previous answers: If foo is the instance variable backing the foo property, then this is not a leak, since the setFoo: method that you call in the second line will release the object that you put in the foo instance variable in the first line..


6:


I don't think so as by doing self.foo = nil you are essentially using the setter and getting the memory management along for free..


7:


Since nobody else seems to have noticed: There might be a leak.. I'll assume that foo is both an ivar and a retain property:.
@interface Foo : NSObject {   NSObject * foo; } @property (nonatomic, retain) NSObject * foo; @end 
Let's say your code looks something like this:.
-(void)bar {   foo = [[NSObject alloc] init];   self.foo = nil; } 
That, in itself does not leak provided foo was nil to start with.

That doesn't mean it won't leak — let's say you add some more code:.
-(void)baz {   self.foo = [[NSObject new] autorelease]; }  -(void)fubar {   [self baz];   [self bar]; } 
Stuff like foo = [[Foo alloc] init] is generally safe in init-methods because it's assumed that you only call one of them, so foo is guaranteed to be nil initially.

Everywhere else, you have to be a bit more careful..
// Use assertions so it crashes debug builds if it's already set assert(!foo); foo = [[NSObject alloc] init]; self.foo = nil;  // Or release explicitly. 

[foo release]; foo = [[NSObject alloc] init]; self.foo = nil; // Or just use the setter, which will do the "right thing".

// This is particularly relevant for "copy" or "assign" accessors.

self.foo = [[[NSObject alloc] init] autorelease]; self.foo = nil;



86 out of 100 based on 66 user ratings 1166 reviews