Why is there no autorelease pool when I do performSelectorInBackground:?
Asked Answered
R

2

5

I am calling a method that goes in a background thread:

[self performSelectorInBackground:@selector(loadViewControllerWithIndex:) withObject:[NSNumber numberWithInt:viewControllerIndex]];

then, I have this method implementation that gets called by the selector:

- (void) loadViewControllerWithIndex:(NSNumber *)indexNumberObj {
    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init];
    NSInteger vcIndex = [indexNumberObj intValue];

    Class c;
    UIViewController *controller = [viewControllers objectAtIndex:vcIndex];

    switch (vcIndex) {
        case 0:
            c = [MyFirstViewController class];
            break;
        case 1:
            c = [MySecondViewController class];
            break;
        default:
            NSLog(@"unknown index for loading view controller: %d", vcIndex); // error
            break;
    }

    if ((NSNull *)controller == [NSNull null]) {
        controller = [[c alloc] initWithNib];
        [viewControllers replaceObjectAtIndex:vcIndex withObject:controller];
        [controller release];
    }

    if (controller.view.superview == nil) {
        UIView *placeholderView = [viewControllerPlaceholderViews objectAtIndex:vcIndex];
        [placeholderView addSubview:controller.view];
    }

    [arPool release];
}

Althoug I do create an autorelease pool there for that thread, I always get this error:

2009-05-30 12:03:09.910 Demo[1827:3f03] *** _NSAutoreleaseNoPool(): Object 0x523e50 of class NSCFNumber autoreleased with no pool in place - just leaking
Stack: (0x95c83f0f 0x95b90442 0x28d3 0x2d42 0x95b96e0d 0x95b969b4 0x93a00155 0x93a00012)

If I take away the autorelease pool, I get a whole bunch of messages like these. I also tried to create an autorelease pool around the call of the performSelectorInBackground:, but that doesn't help.

I suspect the parameter, but I don't know why the compiler complains about an NSCFNumber. Am I missing something?

My Instance variables are all "nonatomic". Can that be a problem?

UPDATE: I may also suspect that some variable has been added to an autorelease pool of the main thread (maybe an ivar), and now it trys to release that one inside the wrong autorelease pool? If so, how could I fix that? (damn, this threading stuff is complex ;) )

Rizas answered 30/5, 2009 at 10:16 Comment(3)
Try setting a breakpoint on _NSAutoreleaseNoPool to see where it is being called fromTartarean
Tangent question: here a new controller, allocated locally in this thread, is added to a global array and also its view is added as a subview. Is this a problem in that the object is created in a different pool than its container?Oceania
@dk you shouldn't ask a tangent question, ask a separate question! Anyway I strongly advise against creating UI related objects (controllers and views) in a non-main thread. That's a disaster waiting to happen.Not
E
7

Most likely the reason for this is because the leaked object (an NSNumber), is a parameter passed in from outside the thread. Hence, this variable belongs to the calling thread (and its autorelease pool)

The reason that the autorelease pool around the thread call doesn't work, is because the thread creator (performSelectorInbackground) - returns immediately, most likely while the thread is still running.

I suggest you do a release on your selector's parameter after passing it in as an argument.

Enkindle answered 30/5, 2009 at 10:47 Comment(1)
Yes, passing autoreleased objects into new threads can cause very strange behavior.Thamora
D
3

I agree that most likely the reason for this is because the leaked object (an NSNumber), is a parameter passed in from outside the thread. Hence, this variable belongs to the calling thread (and its autorelease pool)

The calling thread should use NSAutoreleasePool and I suggest that you add a retain instruction to your parameter as:

- (void) loadViewControllerWithIndex:(NSNumber *)indexNumberObj {
    NSAutoreleasePool *arPool = [[NSAutoreleasePool alloc] init];
    [indexNumberObj retain];

    ....

    [arPool release];
  }
Drug answered 12/6, 2010 at 2:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.