0
votes

how can i solve this potential leak ?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

NSUInteger row = [indexPath row];
Chapter *chapter =[Chapter alloc] ;

switch (indexPath.section) {
    case 0: 
        chapter = [einfuerung objectAtIndex:row];
        break;
    case 1: 
        chapter = [vertiefung objectAtIndex:row];
        break;
    case 2: 
        chapter = [spezial objectAtIndex:row];
        break;
}

if ([[NSFileManager defaultManager] fileExistsAtPath:[chapter urlOnFilesystem]]) {

    dataInstance.chapter = chapter;

    Container *container = [[Container alloc] init];
    [self.navigationController pushViewController:container animated:YES];
    [container release];
}
else{

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Kapitel nicht vorhanden" message:@"Kapitel wurde noch nicht heruntergeladen" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

[chapter release];

}

Xcode tells me two problems with chapter.

  1. Incorrect decrement of the reference count of an object that is not owned at this point.
    Why is this object not owned by me ?

  2. Potential leak of an object.. (chapter)
    How release it correctly?
    [chapter autorelease]] ?

3

3 Answers

4
votes

You should not alloc the chapter in below statement.

Chapter *chapter =[Chapter alloc] ;

Use below instead.

 Chapter *chapter = nil;

I have modified your code

NSUInteger row = [indexPath row];
 Chapter *chapter = nil;

switch (indexPath.section) {
    case 0: 
        chapter = [[einfuerung objectAtIndex:row] retain];
        break;
    case 1: 
        chapter = [[vertiefung objectAtIndex:row] retain];
        break;
    case 2: 
        chapter = [[spezial objectAtIndex:row] retain];
        break;
   default:
        chapter =[[Chapter alloc] init];
        break;
}

if ([[NSFileManager defaultManager] fileExistsAtPath:[chapter urlOnFilesystem]]) {

    dataInstance.chapter = chapter;

    Container *container = [[Container alloc] init];
    [self.navigationController pushViewController:container animated:YES];
    [container release];
}
else{

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Kapitel nicht vorhanden" message:@"Kapitel wurde noch nicht heruntergeladen" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

[chapter release];

}
3
votes
Chapter *chapter =[Chapter alloc];

You have not sent init but that is not the reason of leak. The problem is in the switch-case.

chapter = [einfuerung objectAtIndex:row];

When you are doing this you are pointing to a new chapter object, and the previous alloced one is leaked. If you are always getting a Chapter object from an array (i.e. you have at most three sections) then you don't need the alloc. Just declare it, and you don't need to release then too.

0
votes

You first allocate an object and assign it to chapter. You forgot to initialize it, but that's not the problem.

The problem arises when you overwrite chapter in your switch statements. The reference to the previously allocated object is lost and the object thus leaked.

You need to do two things:

  1. Chapter *chapter = nil;
  2. Remove the [chapter release]; at the end since you are not the owner of the elements returned by [someArray objectAtIndex:row].