2

My app is crashing on Lion when it awakes from sleep. The problem seems to be with a background thread that is looking for weather info. I'm not sure but I think the crash log is telling me that the autorelease pool is popping objects that are no longer there, can someone help me confirm this?

Here is the relevant details for the Crash log:

Process: myApp [14187] Identifier: myApp Version:
??? (???) Code Type: X86-64 (Native) Parent Process: launchd [224]

Date/Time: 2011-08-24 18:58:00.581 -0400 OS Version: Mac OS X 10.7.1 (11B26) Report Version: 9

Crashed Thread: 7

Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010

Application Specific Information: objc[14187]: garbage collection is OFF

Thread 7 Crashed: 0 libobjc.A.dylib
0x00007fff9321700b (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 385 1
com.apple.CoreFoundation 0x00007fff961306a5 CFAutoreleasePoolPop + 37 2 com.apple.Foundation
0x00007fff969350d7 -[NSAutoreleasePool drain] + 154 3
com.piso13.opusDomini 0x00000001000acb91 -[Weather internalStart] + 417 4 com.apple.Foundation
0x00007fff9698b1ea -[NSThread main] + 68 5 com.apple.Foundation
0x00007fff9698b162 NSThread
_main + 1575 6 libsystem_c.dylib
0x00007fff90b068bf _pthread_start + 335 7 libsystem_c.dylib
0x00007fff90b09b75 thread_start + 13

Here is my code for Weather Internal Start:

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

    forecast = FALSE;
    liveweather = FALSE;

    NSString *query = [self generateQuery];
    if (query == nil) {
        [pool drain];
        return;
    }


    XmlWrapper * xmlWrapper = [[XmlWrapper alloc] initWithQuery:query delegate:self name:@"liveweather"];
    [xmlWrapper release];

    query = [self generateForecastQuery];
    xmlWrapper = [[XmlWrapper alloc] initWithQuery:query delegate:self name:@"forecast"];
    [xmlWrapper release];

    [pool drain];

}

Should I even be calling [pool drain] ?

the Reverend
  • 12,305
  • 10
  • 66
  • 121
  • Nothing looks wrong here... Can you show some of `generateForecastQuery` or `generateQuery`? Or maybe your `XmlWrapper` class? – jtbandes Aug 25 '11 at 17:44
  • Where did you copy that crash log from? It's all miswrapped. Please copy it from the original crash log file in your ~/Library/Logs folder and edit your question to include that text with code formatting. – Peter Hosey Aug 25 '11 at 18:47
  • 2
    Immediately releasing your `XMLWrapper` objects as soon as you create them is a red flag. Why are you doing this? – Rob Keniger Aug 26 '11 at 03:13
  • Peter the crash log is not in my computer, it was sent to me.. my apologies. – the Reverend Aug 29 '11 at 23:03

2 Answers2

4

create your autorelease pools with bound lifetimes and explicit scopes.

in this case, you store your autorelease pool in an ivar (presumed).

just make it local to the method, like so:

- (void)internalStart
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    //...
    [pool drain], pool = nil;
}

the problems that are typically introduced are:

1) autorelease pools are stack based (pools are pushed and popped). by holding onto it, you can easily mess up the stack order.

2) if this class operates in a multithreaded context, you can easily leak pools or destroy the stack order when you push and pop pools from multiple threads.

3) you could also leak pools in multithreaded contexts

justin
  • 104,054
  • 14
  • 179
  • 226
  • 3
    More simply: When this method runs on two different threads, each thread will put its own autorelease pool into the `pool` instance variable—but since the instance variable is, by definition, *per-instance*, both threads are putting their pools into the same place. Only one wins, and then both threads try to drain that same pool. That's the crash. – Peter Hosey Aug 25 '11 at 18:51
  • Peter thank you thats the crash....Can you help me with the releasing too soon? This xmlWrapper reads info from the internet and sends a message to the delegate (the caller) when the weather info is ready. Could the xmlWrapper be destroyed while processing? – the Reverend Aug 29 '11 at 22:59
3

Unfortunately, autoreleasepool crashes are some of the hardest to debug. Start with the static analyzer, which can find some things.

Then turn on NSZombies.

Your XmlWrapper object is a bit strange. Why do you immediately release it as soon as you create it? Is this a wrapper around NSURLConnection? You should still hold onto the object so that you can cancel it or clear its delegate when this object is released.

Make sure you're using accessors for all your ivars rather than accessing them directly. Direct access to ivars outside of init and dealloc is the #1 cause of these kinds of crashes in my experience.

Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • From your comments, I think I may be releasing xmlWrapper too soon. The xmlwrapper will send the delegate (current caller) a message that the information is ready for reading. Can this object be released in the middle of its internal processing before sending the delegate the finish message? – the Reverend Aug 29 '11 at 22:53