Reputation: 1541
I am getting a crash in the app with the following stack trace-
Thread : Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x39dfa66a objc_release + 9
1 libobjc.A.dylib 0x39dfb0d7 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358
2 CoreFoundation 0x2f4a6c69 _CFAutoreleasePoolPop + 16
3 CoreFoundation 0x2f53c1cb __CFRunLoopRun + 1306
4 CoreFoundation 0x2f4a6f0f CFRunLoopRunSpecific + 522
5 CoreFoundation 0x2f4a6cf3 CFRunLoopRunInMode + 106
6 GraphicsServices 0x343ff663 GSEventRunModal + 138
7 UIKit 0x31df216d UIApplicationMain + 1136
8 Batted 0x0009db07 main (main.m:16)
The crash occurs when zombies are not enabled in the Scheme's diagnostics options. However, when I enabled it the crash doesn't occur.
I have read some of the other Q&A regarding this, and all of them seem to advice that once this behavior is seen, enable the zombies and run the Zombie Profile Instruments on the Simulator.
I tried that, but Instruments doesn't seem to indicate anything wrong and the app works. Any clue to what else can be done here to root-cause this issue? I am using XCode 5.1 with iOS 7.1 in Simulator.
UPDATE 1
Found the offending code causing the problem but I am still not sure why it is causing the problem. I am using CoreData, and in subclass of the NSManagedObject, I have -
- (void)willTurnIntoFault;
{
[super willTurnIntoFault];
if ([self observationInfo])
{
BNLogInfo(@"%@ has observers:\n%@", [self objectID], [self observationInfo]);
}
}
In the above code, [self observationInfo]
is the offending line.
When the app starts up, I loop over some of the NSManagedObjects in an enumeration block and set some property on it, which in turn fires the willTurnIntoFault
method. Once the enumeration block completes, the crash happens.
The mystery is that the crash doesn't happen inside this method, but without this method subclassed everything runs fine.
Upvotes: 1
Views: 753
Reputation: 385960
The Q&As say to enable zombies (or run under the Zombies instrument) because a zombie often causes this sort of error.
But it's not the only cause.
Your program is corrupting the heap. Most likely it's overwriting the isa
pointer (the class pointer) in some object that's in the autorelease pool, so when the run loop drains the autorelease pool, objc_release
tries to dereference the bogus isa
pointer and crashes.
Enabling zombies can mask an error like this because, with zombies, the runtime never actually frees objects. This means you end up with lots of parts of the heap that don't get used (unless you try to send a message to a zombie), so they never cause trouble if you corrupt them.
These sorts of crashes can be very difficult to debug, but there's a tool called “guard malloc” that sometimes helps. From the menu bar, choose Product > Scheme > Edit Scheme. Click the Run action in the list on the left. Then click the Diagnostics tab. Turn on the “Enable Guard Malloc” option. Then try to reproduce the crash. Guard malloc will detect certain types of heap corruption immediately and stop the program on the corrupting instruction.
Upvotes: 2