Question

So, I am using [NSThread detachNewThreadSelector] to spawn a new thread and I am getting "autoreleased with no pool in place " errors in the console. I know this can happen if you fail to create an auto release pool, but the thing is, I am creating one. I use similar code in other parts of the same app and do NOT get these errors.

Here is the relevant code:

- (void) startThread:(NSString*)strURL
{
    // start new thread to load image
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [NSThread detachNewThreadSelector:@selector(loadImageFromURL:) toTarget:self withObject:strURL];
    [pool release];
}

- (void) loadImageFromURL:(NSString*)strURL
{
    NSNumber* nn = [NSNumber numberWithInt:self.tag];
    NSLog(@"loadURL: Tag number == %i", [nn intValue]);

   // other code here actually does the work
}

Now, there was more code in loadImageFromURL which actually does the work (of loading an image from a remote server) - but the problem manifests itself without that code, so I've removed it (just so you don't think I have a pointless thread which does nothing!). I left in just one line of code which demonstrates the problem - it creates an autoreleased NSNumber object.

When this code runs, it reports this to the console:

__NSAutoreleaseNoPool(): Object 0x535c0e0 of class NSCFNumber autoreleased with no pool in place - just leaking

Of course, the real code creates many other AR objects and all of them get reported as well.

Would be grateful for any tips or pointers which might help!

Thanks!

Was it helpful?

Solution

When you create a new thread, you need to also create a new autorelease pool for it. In your case, that looks as simple as adding:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

at the beginning of loadImageFromURL: and

[pool drain];

at the end.

You probably don't need or want the pool you're creating in startThread:. Check out the Threading Programming Guide, particularly the "Writing Your Thread Entry Routine" section.

OTHER TIPS

On your code, - (void) startThread:(NSString*)strURL is running in the main thread, while - (void) loadImageFromURL:(NSString*)strURL is running on the background thread you are detaching.

The main thread already has a NSAutoreleasePool, so the one you are creating in startThread: is probably unneeded. However, the background thread will not create a NSAutoreleasePool, so you'd need to create it yourself.

In your code, that would look like:

- (void) startThread:(NSString*)strURL
{
    // start new thread to load image
    [NSThread detachNewThreadSelector:@selector(loadImageFromURL:) toTarget:self withObject:strURL];
}

- (void) loadImageFromURL:(NSString*)strURL
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSNumber* nn = [NSNumber numberWithInt:self.tag];
    NSLog(@"loadURL: Tag number == %i", [nn intValue]);

   // other code here actually does the work

    [pool drain];
}

Also, as @Carl Norum suggested, you should use drain instead of release when you are done using the autorelelase pool.

Solution for a similar problem but using ARC.

If using ARC, you could get an error "'NSAutoreleasePool' is unavailable: not available in automatic reference counting mode".

Use:

- (void) startThread:(NSString*)strURL
{
    // start new thread to load image
    [NSThread detachNewThreadSelector:@selector(loadImageFromURL:) toTarget:self withObject:strURL];
}

- (void) loadImageFromURL:(NSString*)strURL
{
    @autoreleasepool {          
        NSNumber* nn = [NSNumber numberWithInt:self.tag];
        NSLog(@"loadURL: Tag number == %i", [nn intValue]);

        // other code here actually does the work   
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top