Mausimo
Mausimo

Reputation: 8168

Why is this Objective-C code leaking memory?

Why does this leak?

The arrayOfPerformances is a NSMutableArray, (nonatomic, retain) property that is synthesized.

The currentPerformanceObject is a Performance *, (nonatomic, retain) property that is synthesized.

Performance is a custom class

if(self.arrayOfPerformances == nil)
    {
        self.arrayOfPerformances = [[NSMutableArray alloc]init];
    }

    [self.arrayOfPerformances addObject:currentPerformanceObject];
    [currentPerformanceObject release];
    currentPerformanceObject = nil;

Upvotes: 3

Views: 163

Answers (3)

Nick Forge
Nick Forge

Reputation: 21464

If your .arrayOfPerformances property is never released (it would usually be released in -dealloc), than the array itself, plus any object in the array will be leaked when this object is dealloced.

You need to release both properties in your -dealloc:

- (void)dealloc
{
    ... other deallocs
    self.arrayOfPerformances = nil;
    self.currentPerformanceObject = nil;
    [super dealloc];
}

Also, as @BoltClock has pointed out, you need to release or auto-release your NSMutableArray. The best way to do this is to initialize it using the autoreleased method:

self.arrayOfPerformances = [NSMutableArray array];

Also, you don't need to release your currentPerformanceObject, you should just set the property to nil, since setting the retained property to nil will release it for you. Your code should probably look something like this:

if (self.arrayOfPerformances == nil) {
    self.arrayOfPerformances = [NSMutableArray array];
}
[self.arrayOfPerformances addObject:self.currentPerformanceObject];
self.currentPerformanceObject = nil;

Upvotes: 4

BoltClock
BoltClock

Reputation: 723498

You are creating a new array and retaining it at the same time in this line, because you are invoking a (retain) property setter with the dot notation:

// Your property
@property (nonatomic, retain) NSMutableArray *arrayOfPerformances;

// The offending code
self.arrayOfPerformances = [[NSMutableArray alloc]init];

Because of that, the locally-created array is leaking because you don't release it. You should autorelease that array, or create a temporary local var, assign, then release the local var, like so:

// Either this
self.arrayOfPerformances = [[[NSMutableArray alloc] init] autorelease];

// Or this (props Nick Forge, does the same as above)
self.arrayOfPerformances = [NSMutableArray array];

// Or this
NSMutableArray *newArray = [[NSMutableArray alloc] init];
self.arrayOfPerformances = newArray;
[newArray release];

Upvotes: 11

Adam Milligan
Adam Milligan

Reputation: 2826

This line is the culprit:

self.arrayOfPerformances = [[NSMutableArray alloc]init];

The retain count is 1 after the alloc/init. Setting the value via the arrayOfPerformances property setter increments the retain count again (because it's a retain property).

Upvotes: 1

Related Questions