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:开发者_StackOverflow 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] ?
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
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.
精彩评论