views:

81

answers:

4

Hi, What is causing the leaks in this code? I really cannot understand it. On thes lines: 1: NSMutableArray * days = [[NSMutableArray alloc]init]; 2: [dic setObject:days forKey:key]; 3: [days addObject:value];

The whole method:

-(void) addValueToDictionary: (NSMutableDictionary *) dic withValue: (NSNumber *) value forKey: (NSString *) key {
NSMutableArray * days =  [dic objectForKey:key];
if (days == nil) {
    NSMutableArray * days = [[NSMutableArray alloc]init];
    [days addObject:value];
    [dic setObject:days forKey:key];
    [days release];
    days = nil;
}
else {
    [days addObject:value];
}

}

BR //Christoffer

A: 

Have you tried to change the name of the variable NSMutableArray *days within the if? Don't you get a warning because of that?

toupper
+1  A: 

Check to make sure that dic is released. You should NSLog retainCount before where you think the final releases are and make sure they are 1 right before the final release.

Also, run a Build and Analyze to make sure you are releasing correctly. The built in Build and Analyze doesn't find as many leaks as running scan-build with all checks, so look into installing scan-build into Xcode as well.

http://stackoverflow.com/questions/3297986/using-an-external-xcode-clang-static-analyzer-binary-with-additional-checks

Lou Franco
Forget about the retain count. It's misleading at best. You should use the Apple memory management debugging tools and static analyser to detect the causes of leaks.
JeremyP
Why do you think the retainCount is misleading? At some point, when debugging, if you check what you think the final release is (which you often have a good idea of) -- the retainCount should be one right before it. If not, you might have forgotten a release somewhere else.
Lou Franco
A: 

There's nothing wrong with that particular piece of code (other than the slightly questionable redefinition of days in the inner scope). Somewhere else you are retaining but forgetting to release the object you put in the dictionary.

JeremyP
+1  A: 

You should be getting a warning about re-declaring days. This may be throwing the leak check off if you are using the static analyser. Modified method below. Mostly coding style changes with a little defensive coding added.

-(void) addValueToDictionary: (NSMutableDictionary *) dic withValue: (NSNumber *) value forKey: (NSString *) key 
{
    if (nil == dic || nil == key || nil == value) return; // bail out on nil parameters 
    if (![dic objectForKey:key]) {
        NSMutableArray * days = [[NSMutableArray alloc] init];
        [dic setObject:days forKey:key];
        [days release];
    }
    [[dic objectForKey:key] addObject:value];
}
falconcreek