views:

88

answers:

3

Hi all, I want to clarify whether there is a memory leak in this code? As far as I feel its there.

in .h file

@interface MyClass{
     NSMutableArray *dataArray;    
}

@property(nonatomic,retain) NSMutableArray *dataArray;

in .m file

-(id) init{    
    self. dataArray = [[NSMutableArray alloc]init];    
}

-(void) dealloc{   
    [self.dataArray release];
    [super dealloc];
}
A: 

Take the self.'s out because those are acting as the getters, it's not like Java or other languages. Otherwise it looks fine.

Kurbz
Why the down vote? It's generally considered good practice not to use the property accessors in init and dealloc but to use the ivars..
JeremyP
Yes, but this answer doesn't state that, or explain why removing the "self." fixes the memory leak ("it's not Java" isn't the answer :-). [ and no, I didn't downvote it ]
David Gelhar
+2  A: 

Yes, there is a leak there.

Should be

self.dataArray = [[[NSMutableArray alloc] init] autorelease];

Since dataArray is defined as a retain property, using self.dataArray on the left-hand side of an assignment implies a retain on the right-hand side.

edit: ...plus a release on the object that had previously been stored in self.dataArray, which is nil at the time of the init call.

Pumbaa80
Yechh. Why not just `self.dataArray = [NSMutableArray array];`? Either do that or else, `dataArray = [[NSMutableArray alloc] init];`. Note that the expression `self.dataArray = x` is translated by the compiler into `[self setDataArray:x]`.
jlehr
+1  A: 

Yes, there is a leak in init. dataArray is declared with the retain attribute. So it retains the given array. But since you allocated it you own it and you have to release it afterwards.

Also the dealloc is not good. This code may crash under some circumstances (probably not here) because you release an object you don't own.

Should be something like this:

-(id) init {
    NSMutableArray *array = [NSMutableArray new];
    self.dataArray = array;
    [array release];
}

-(void) dealloc {
    self.dataArray = nil;
    [super dealloc];
}
nils
Hi nils,Why dont you release the dataArray in deallc method? Its a must here.
charith
Since it's an retained property the setter releases the old value.
nils
How does `[self.dataArray release]` "release an object you do not own"? That's a pretty common idiom in dealloc -- release all iVars you retain'ed. You could argue that using the setter via `self.dataArray = nil` is better style (because it eliminates the reference to the released object), but the effect is the same.
David Gelhar
@David Guess that's just something that Apple didn't explain very well in http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-SW1 - they're not talking about properties/generated accessors there. So by Apple's definition you don't own objects that are assigned to properties.
Pumbaa80
@David Guess: That's not common (or at least it shouldn't). If you access the ivar through it's getter you get an object you don't own: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html. So you must not release it. [dataArray release] is ok (one may argue about the style), but [self.dataArray release] not. It is probably already autoreleased and so the autorelease pool later may send a release message to some invalid (or worse: valid) location.
nils
missing a couple semi-colons there
Kurbz
How about`-(id)init { [self.dataArray = [NSMutableArray new] release]; }`?
nicerobot
@nils Good point; if there's a non-default getter that returns an autoreleased object, [self.dataArray release] is not cool. You can get away with it in this case (assuming the default getter), but that's playing with fire...
David Gelhar
@David Gelhar: Is somewhere defined what the default getter does? I suppose it has to autorelease it. I do not see how else it can prevent a leak.@nicerobot: No then the object is killed before the setter can retain it. You can use autorelease in this case…
nils