views:

310

answers:

3

I have a hard time grasping this memory leak in my code. Basically it's returning an object containing a object. here's the following code:

-(id) getOptions {
    FileManager *file = [[FileManager alloc] initWithFileName:@"optionsFile.dat"];
    Options *options = [[Options alloc] init];
    NSMutableArray *fileArray = [[NSMutableArray alloc] init];
    fileArray = [file loadFile: @"optionsFile"];

    if ([fileArray count] > 0) {
     options = [fileArray objectAtIndex:0];
    }
    [file release];
    return options;
}

I try to retain the returned object and releasing right after using:

id options = [[self getOptions] retain];
[options release];

Basically, from the iphone documentation, i should have it autoreleased on my mutatbe array for filearray, but i am still getting a memory leak, anyone can shed some light on this, would be greatly appreciated.

EDIT:

I just added this to see if it would solve anything, but i am still leaking:

FileManager *file = [[FileManager alloc] initWithFileName:@"optionsFile.dat"];
NSMutableArray *fileArray = [file loadFile: @"optionsFile"];
Options *options = [fileArray objectAtIndex:0];
[file release];
return options;
+4  A: 

For each init or retain call, you should call release (or autorelease).

The Options object is missing a release call. You should either, not retain the returned object from getOptions, or return an autoreleased instance. The convention is usually to return an autoreleased object, to do this, just change the return statement to:

return [options autorelease];

This way, if the caller wants to retain it they can, but if they're just using the result and discarding the object, they don't have to do anything and it'll be released by the autorelease pool.

Also, fileArray is not released. Once you're done with it, call [fileArray release];

You should probably read over parts of the Memory Management Guide to get a better understanding of how to manage this sort of leak.

Ben S
when i add a [fileArray release] it breaks my app, i am wondering if it has to do with when i am doing this: options = [fileArray objectAtIndex:0];
Frank
You shouldn't even be doing an alloc + init, just assign the result of `[file loadFile: @"optionsFile"]` to the variable.
Ben S
A: 

Based on what you have here, you should, if nothing else, expect fileArray to leak since you alloc it but never either put it in the autorelease pool or release it. Try putting it in the autorelease pool and see if that helps.

Gordon Worley
A: 

Looking at it, Options and fileArray are leaking. The code should look like this:

-(id) getOptions {
   FileManager *file = [[FileManager alloc] initWithFileName:@"optionsFile.dat"];
    Options *options = [[Options alloc] init];
    //NSMutableArray *fileArray = [[NSMutableArray alloc] init]; This instance was leaking
    //fileArray = [file loadFile: @"optionsFile"]; 
    NSMutableArray *fileArray = [file loadFile: @"optionsFile"];

    if ([fileArray count] > 0) {
        options = [fileArray objectAtIndex:0];
    }
    [file release];
    return [options autorelease];
}

I am not sure what loadFile returns, I'm expecting an autoreleased object in this code.

Elfred
`options` still leaks if `[fileArray count] > 0`.
dreamlax
fileArray returns an autoreleased object
Frank
dreamlax is correct, there is an options leak as well.
Elfred