Reputation: 50826
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?
Upvotes: 2
Views: 1529
Reputation: 33592
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;
Upvotes: 0
Reputation: 96333
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.
Upvotes: 1
Reputation: 107754
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.
Upvotes: 1
Reputation: 26859
Nope, the second example is not a memory leak. 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.
Upvotes: 2
Reputation: 40517
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).
Upvotes: 1
Reputation: 3569
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.
Upvotes: 0
Reputation: 29759
self.foo = nil
would translate into
[nil retain]
[foo release]
foo = nil
There is no memory leak here.
Upvotes: 4