开发者

Attempt to pop an unknown autorelease pool

Does any开发者_运维百科one know what this error means? *** attempt to pop an unknown autorelease pool

I am seeing this in my app that uses NSOperations in NSOperationQueue. Each operation has it's own Autorelease pool. Since each operation is parsing xml and pushing information into Core Data, I periodically 'drain' my autorelease pool and re-create it. If I don't drain the pool, I don't see these errors.

UPDATE: Here's my code:

In the main of my NSOperation, I alloc the pool and assign it to an 'assign' property like this:

self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];

at the end of my main I release it like this:

[self.downloadAndParsePool release];
self.downloadAndParsePool = nil;

If the operation does a lot of parsing and inserting into Core Data, it will call my drain method periodically:

- (void) drainAutoreleasePool
{
    // drain and re-create autorelease pool...this method is called periodically to keep memory down during parsing of large trees
    if (self.downloadAndParsePool)
    {
        [self.downloadAndParsePool drain];
        self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
    }
}


It seems that the issue is caused by the fact that the drain is called outside of the method that allocated the pool even if on the same thread. Here is what NSAutoreleasePool Class Reference says.

You should always drain an autorelease pool in the same context (invocation of a method or function, or body of a loop) that it was created.

The message you see is triggered by your call to drain in drainAutoreleasePool:

[self.downloadAndParsePool drain];

NOTE: XMLPerformance sample app uses the same pattern of periodically draining the pool. It also produces this message since iOS4.0


How To Actually Fix This

The accepted answer here is correct, but here are some more details on how to fix it because it's not a good idea to just live with issues that are filling up your console. A log statement is being printed and there is a reason for it. Something is awry.

Turns out this code is from Apple's own example project called XMLPerformance, found here: http://developer.apple.com/library/ios/#samplecode/XMLPerformance/Introduction/Intro.html

In the source file, LibXMLParser.m, simply change this line:

self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];

to this:

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

at the beginning of the - (void)downloadAndParse:(NSURL *)url method and then change:

[downloadAndParsePool release];
self.downloadAndParsePool = nil;

to this:

[pool release], pool = nil;

at the end of that method. Now remove the ivar called downloadAndParsePool. Once you've done all of that, the messages will go away.

Magically delicious.


It sounds like you've lost a pool somewhere. Pools are objects and its possible for them to be over released. They also stack in a fashion. IIRC, when you have nested pools, draining an outer pool automatically drains the inner pools. I think you've got a pool object that dies without being drained. When the outer pool tries to drain it, it never gets a response.

Just a guess.


It would be very helpful if you could show the code that does the creation of the pool, the drain of the pool and the re-creation of it. Otherwise we are just guessing at answers.

update

First, pools like that should be a local variable inside of the -main instead of an iVar like that. Second, how is your property defined? Is it an assign or a retain?

Update2

I would still recommend against using an iVar to store that pool. Nevertheless since it is an assign that should be fine.

When you drain the pool, are you also saving and resetting the NSManagedObjectContext associated with that operation? NSManagedObjectContext makes very heavy use of the autorelease pool and if you are not resetting it at the same time as the drain that could be causing an error.

Update3

Ok, then we are left with TechZen's suggestion that you are losing a pool somewhere. I would put log statements in after you create a pool and spit out its pointer address and put a log statement in just before the drain that also spits out the pointer address. Then match them up. If they match up then the leak is somewhere else.


If you create a pool with NSAutoReleasePool

So that it automatically releases there is no need for release in dealloc

The app sometimes crashes if you use NSAutoReleasePool and also release the pool in dealloc

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜