Search code examples
objective-ciosmemory-managementdealloc

Locating a memory leak/source of over-release crach


Can anyone help me figure out where I should be releasing exerciseArray? I get a crash in dealloc and when I release just before calling sortedArray. This code is called many times.

//Set exerciseArray
review.exerciseArray = [[workout assignedExercises] allObjects];

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"viewWillAppear");
    NSString *workoutName =  [event.assignedWorkout valueForKey:@"name"];
    self.title = workoutName ;

    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"index"
                                                                    ascending:YES] autorelease];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    [sortedArray release];
    sortedArray= [exerciseArray sortedArrayUsingDescriptors:sortDescriptors];
    NSLog(@"*****SORTEDARRAY****** %d",[sortedArray retainCount]);
    for (Exercise *ex in sortedArray){
        NSLog(@"%@ %@ %@",ex.name , ex.repCount, ex.weight);
    } 
    NSLog(@"*********************");
    [sortedArray retain];
    [self.tableView reloadData];
}

 - (void)dealloc {
    [super dealloc];

    [managedObjectContext release];
    [event release];
}

Solution

  • First things first: You should move the [super dealloc] call to the end of your dealloc method. Handle your custom variables first, and then the last thing you do is push the dealloc up to the superclass to handle the rest of the cleanup.


    Now, I'm concerned about the [sortedArray release] and [sortedArray retain] in there. What you should be doing, to save you the semantics of implementing retain/release on your sortedArray ivar, is declaring a property for sortedArray like so:

    // this goes in your @interface
    @property (nonatomic, retain) NSArray *sortedArray;
    
    // this goes in your @implementation
    @synthesize sortedArray;
    

    Now you can set sortedArray easily without worrying about retaining or releasing:

    // note the use of self, this is required
    self.sortedArray = [exerciseArray sortedArrayUsingDescriptors:sortDescriptors];
    

    You can remove the release and retain calls now, as this is handled automatically. Make sure to add a line to your dealloc method to clean up the variable, too..

    self.sortedArray = nil;
    

    ..which will call release on your array for you.

    EDIT: This also applies to exerciseArray, which was your actual question. Wherever there's a Cocoa class involved, you can simplify memory management using @property (retain) and @synthesize. For NSInteger and other primitive types, or when you don't want to hold an owning reference to the object, use @property (assign) instead.