Alede
Alede

Reputation: 109

Leak in NSMutableArray

I have been pulling out my hair trying to figure out why this is leaking. In my .h file I have a synthesized property nonatomic, retained NSMutableArray. In my viewDidLoad I declare it as:

self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);

Throughout my application, I call [self.tableData removeAllObjects] and then repopulate it with the fillData(self.tableData) function. This function fills up the data from a static C++ string set:

void fillData(NSMutableArray* list)
{
    for (set<string>::const_iterator itr = sortedData.begin(); itr != sortedData.end(); ++itr){
        [list addObject:[NSString stringWithFormat:@"%s", ((string)*itr).c_str()]];
    }
}

In my dealloc method I do:

[self.tableData removeAllObjects], [self.tableData release], tableData = nil;

Where did I drop the ball? Instruments says it's in the [list addObject....] line.

Thanks

Upvotes: 1

Views: 290

Answers (4)

Rudy Velthuis
Rudy Velthuis

Reputation: 28806

In your dealloc, you use properties which retain the tableData again. That is not really what you want, so do:

[tableData release];

or

[self->tableData release]; // not necessary, but some prefer it.

or

self.tableData = nil; // property will handle release

No need to clear the tableData, no need to set anything to nil (you are deallocating, so nothing will access it anymore).

Upvotes: 0

sharvey
sharvey

Reputation: 8145

The problem is that your property is set as retain, and you set it to an already retained object. You should do it like this:

// viewDidLoad
NSMutableArray *array = [[NSMutableArray alloc] init];
self.tableData = array;
[array release]; // this is important

// dealloc
self.tableData = nil; // will automatically release the array

Upvotes: 0

Stephen Darlington
Stephen Darlington

Reputation: 52565

Not sure if it's the leak, but this looks like it's a problem:

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

You say that tableData is a property that's retained. Try:

self.tableData = [NSMutableArray arrayWithCapacity:10];

That way the property retains it and the array itself is autoreleased. Your release in dealloc will bring the retain count back down to zero.

Upvotes: 0

bbum
bbum

Reputation: 162712

self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);

+1 retain for alloc, +1 retain for using the property's setter. You haven't balanced the +1 from alloc. If you are going to use the setter:

self.tableData = [NSMutableArray array];
fillData(self.tableData);

Note that removeAllObjects in that is completely pointless.

This is odd, too:

[self.tableData removeAllObjects], [self.tableData release], tableData = nil;

First, don't bother removing the objects. When the array is deallocated, it'll release all objects. Secondly, using the setter to call release and then immediately do a direct assignment is inconsistent. Either do:

self.tableData = nil;

Or:

[tableData release], tableData = nil;

(Note that the use of the , in all of this is also purely for your benefit -- it has no impact on generated code.)

Also, use stringWithUTF8String: and not stringWithFormat:.

Upvotes: 4

Related Questions