简体   繁体   中英

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;

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];

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 retain ed 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;

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM