views:

104

answers:

2

My coding contains a memory leak, and somehow I can't find the leak.

Leaks points me in the direction of the way I create "ReportDetailItems"

e.g. areaContainer = [[[ReportDetailItem alloc] init] autorelease];

I've been looking at this for hours and I am at a total loss, the objects reported leaking are "ReportDetailItem", and the NSMutableDictionary contained in those objects.

Please advice.

------[ReportDetailItem.h

@interface ReportDetailItem : NSObject
{
    NSNumber *total;
    NSMutableDictionary *items;

}

@property (nonatomic, retain) NSNumber *total;
@property (nonatomic, retain) NSMutableDictionary *items;

- (NSString *)description;

@end

------[ReportDetailItem.m

@synthesize items, total;

- (id)init {
    if (self = [super init]) {
        self.items = [NSMutableDictionary dictionaryWithCapacity:0];
        DLog("Alloc: %d", [items retainCount]);
    }   


    return self;
}

- (NSString *)description {
    return @"ReportDetailItem";
}

- (void)release {
    [super release];
}

- (void)dealloc {
    [self.items release];
    [self.total release];

    items = nil;
    total = nil;

    [super dealloc];
}

@end

------[Leaking code

NSError *error;
NSArray *data = [self.managedObjectContext executeFetchRequest:request error:&error];
if (data == nil || [data count] == 0) {
    DLog(@"No data.")
} else {
    for (int i=0; i < [data count]; i++) {
        TaskEntity *task = [data objectAtIndex:i];

        NSString *areaKey = task.activity.project.area.title.text;
        NSString *projectKey = task.activity.project.title.text;
        NSString *activityKey = task.activity.title.text;


        ReportDetailItem *areaContainer;
        if (![dataSource objectForKey:areaKey]) {
            areaContainer = [[[ReportDetailItem alloc] init] autorelease];
        } else { 
            areaContainer = [dataSource objectForKey:areaKey];
        }
        areaContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [areaContainer.total intValue])];
        [dataSource setObject:areaContainer forKey:areaKey];


        ReportDetailItem *projectContainer;
        if (![areaContainer.items objectForKey:projectKey]) {
            projectContainer = [[[ReportDetailItem alloc] init] autorelease];
        } else {
            projectContainer = [areaContainer.items objectForKey:projectKey];
        }
        projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
        [areaContainer.items setObject:projectContainer forKey:projectKey];


        ReportDetailItem *activityContainer;
        if (![projectContainer.items objectForKey:activityKey]) {
            activityContainer = [[[ReportDetailItem alloc] init] autorelease];
        } else {
            activityContainer = [projectContainer.items objectForKey:activityKey];
        }
        activityContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [activityContainer.total intValue])];
        [projectContainer.items setObject:activityContainer forKey:activityKey];

    }
}
A: 

I'm pretty skeptic about the two ways u assign pointers to the ReportDetailItem. Why are you trying to autorelease the object in the first place? If not try this

ReportDetailItem *projectContainer;
        if (![areaContainer.items objectForKey:projectKey]) {
            projectContainer = [[ReportDetailItem alloc] init];  
       } else {
            projectContainer = [[areaContainer.items objectForKey:projectKey] retain];
        }
        projectContainer.total = [NSNumber numberWithInt:([task.seconds intValue] + [projectContainer.total intValue])];
        [areaContainer.items setObject:projectContainer forKey:projectKey];

      if(projectContainer) {
       [projectContainer release];
       projectContainer = nil;
      }
Mahadevan S
Thank you for your insight. I am trying to autorelease because somehow they leaked.If I try your suggestion I get "*** -[ReportDetailItem release]: message sent to deallocated instance 0x6ed9ef0"
ByteLock
Did you trying breaking on the [projectContainer release] line ? Maybe you are getting a null pointer. In that case modify the code as above
Mahadevan S
A: 
ByteLock