NSAutorelease memory leak

2019-03-22 08:41发布

问题:

I am getting this error message in the console:

*** _NSAutoreleaseNoPool(): Object 0x10d2e0 of class NSPathStore2
    autoreleased with no pool in place - just leaking

I can't figure out what is the error?

Thanks.

回答1:

This is a classic memory management issue, you are autoreleasing some objects without having an autorelease pool in place. Autoreleasing is not a magic. There is an object of type NSAutoreleasePool that keeps track of all objects you autorelease and ‘from time to time’ releases them:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// An autoreleased object referenced by our pool.
id object = [NSNumber numberWithInt:1]; 
[pool drain];
// Our object no longer valid.

Each thread has to have its own autorelease pool. That’s quite logical, because threads run ‘at the same time’ and if they shared a common autoreleased pool, it could release an object while you are still working with it.

Now the point. There is a default autorelease pool in the main thread of every application, which means you don’t have to think about all of this and autoreleased objects are collected just fine. But if you create another thread, you are usually forced to also create an autorelease pool for this thread. Otherwise there is nobody to claim the autoreleased objects and they just leak. Which is exactly why you are getting the warning.

Leaking thread without an autorelease pool can look like this:

- (void) doSomethingInBackground
{
    id object = [NSNumber numberWithInt:1];
}

- (void) someOtherMethod
{
    [self performSelectorInBackground:@selector(doSomethingInBackground);
}

The fix is simple:

- (void) doSomethingInBackground
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    id object = [NSNumber numberWithInt:1];
    [pool drain];
}

Now you only have to figure out where you are running code in another thread.



回答2:

It sounds like you've spawned a method onto a new thread (possibly using + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument;)

Any method that runs on its own thread will need to have an autorelease pool setup up to catch any autoreleased objects:

- (void)myLovelyThreadedMethod
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    ... // your code here

    [pool release];
}


回答3:

Try using the Clang Static Analyzer