Reputation: 21
Xcode Instruments claims that the below code results in memory leak. As far as I understand, the following happens when assigning a property:
* The old value is autoreleased
* The new value is retained
* The new value is assigned obviously
With that it mind, how come I have a memory leak and how do I resolve it?
"TestProjectViewController.h":
#import <UIKit/UIKit.h>
@interface TestProjectViewController : UIViewController {
NSMutableArray* array;
}
@property (nonatomic, retain) NSMutableArray* array;
@end
"TestProjectViewController.m":
#import "TestProjectViewController.h"
@implementation TestProjectViewController
@synthesize array;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
for(int i = 0; i < 5; i++) {
self.array = [[NSMutableArray alloc] init];
[self.array addObject:@"Hello world #1"];
[self.array addObject:@"Hello world #2"];
}
}
Upvotes: 1
Views: 8877
Reputation: 335
You are initializing the array inside the loop. Thats not necessary at least you assign the value of the array to another object. In that case you would also have to release it inside the loop. You are not either releasing the memory. Since you allocated memory for the array, you should release it too:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.array = [[NSMutableArray alloc] init];//You just need to initialize the array just once
for(int i = 0; i < 5; i++) {
[self.array addObject:@"Hello world #1"];
[self.array addObject:@"Hello world #2"];
}
}
//Finally its necessary to release the memory when the app quits using the release method
[self.array release]
Upvotes: 1
Reputation: 5589
This method leaks because the alloc/init
has an implicit retain and then the property retains it one more time. This results in each array being retained twice. You can either autorelease
the array or release
it at the end of the loop.
As a side note, why are you assigning a property like that in a loop? Only the last array will remain in that property. Instead, you could use a local variable and assign only the last array:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSMutableArray *tempArray = nil;
for(int i = 0; i < 5; i++) {
tempArray = [[[NSMutableArray alloc] init] autorelease];
[tempArray addObject:@"Hello world #1"];
[tempArray addObject:@"Hello world #2"];
}
self.array = tempArray;
}
Upvotes: 0
Reputation: 82545
Each time through the loop, you alloc
a new array. Each array starts with a refcount of 1, and assigning to the property increases it to 2. You need to release
these arrays so that the property is the only "owner" of the object.
For example, you could do this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
for(int i = 0; i < 5; i++) {
self.array = [[NSMutableArray alloc] init];
[self.array addObject:@"Hello world #1"];
[self.array addObject:@"Hello world #2"];
[self.array release];
}
}
or do this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
for(int i = 0; i < 5; i++) {
self.array = [[[NSMutableArray alloc] init] autorelease];
[self.array addObject:@"Hello world #1"];
[self.array addObject:@"Hello world #2"];
}
}
Upvotes: 1
Reputation: 170849
self.array = [[NSMutableArray alloc] init];
Here you retain new array object twice - when allocate it and then in setter method. One of the following should fix that:
self.array = [[[NSMutableArray alloc] init] autorelease];
// or
self.array = [NSMutableArray arrayWithCapacity:someNumber];
and also do not forget to release your array in dealloc method.
Upvotes: 5