views:

800

answers:

1

I am using NSKeyedUnarchiver unarchiveObjectWithFile: to read in application data. When running with Leaks in Instruments, I am told that the following produces a leak:

{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *archivePath = [[NSString alloc]initWithFormat:@"%@/Config.archive", documentsDirectory];

    //Following line produces memory leak
    applicationConfig = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

    [archivePath release];

    if( applicationConfig == nil )
    {
     applicationConfig = [[Config alloc]init];
    }
    else
    {
     [applicationConfig retain];
    }
}

The line:

applicationConfig = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

is producing a memory leak of 32 Bytes. applicationConfig is an instance variable. My initWithCode function simply does:

- (id)initWithCoder:(NSCoder *)coder {
    if( self = [super init] )
    {
                //NSMutableArray
     accounts = [[coder decodeObjectForKey:@"Accounts"] retain];
     //Int
                activeAccount = [coder decodeIntForKey:@"ActiveAccount"];    
    }
    return self;
}

Any idea of why

applicationConfig = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

is producing a leak?

+1  A: 

My guess is that your memory leak is caused by this line:

[applicationConfig retain];

or this line:

accounts = [[coder decodeObjectForKey:@"Accounts"] retain];

The memory is being allocated in unarchiveObjectWithFile:, but the leak will be caused by an extra retain on the object. Make sure that you are releasing applicationConfig appropriately.

Tom Dalling
I thought I read that I have to retain the object that is returned since I didn't alloc it myself. Can you shed any light on this?
Brian
Yes, you do have to retain it. Because you retained it, you also have to release it somewhere. The memory leak will be cause by the lack of the release.
Tom Dalling
I release the applicationConfig in the dealloc method of the application delegate ( where all this code resides ). So then I still don't understand the reported leak. Is it possible it thinks there will be a leak since it doesn't see a matching release in the same method? Thanks for your help.
Brian
You also have to release it before `applicationConfig` is set to any other value. The same applies for the `accounts` member variable.
Tom Dalling
Ah HA! I found it. I am an idiot. I wasn't going far enough down in the stack trace in instruments. I assumed since it didn't give me some where to click to drill down from the NSKeyedUnarchiver, that I couldn't go any further. Account is an object and has its own initWithCoder. Eventually there is a call to SFHFKeychainUtils ( makes saving to key chain easier ) that gives me the password for the account. The call to SFHFKeychainUtils is producing the memory leak. Thanks for your help.
Brian