I've been debugging my iOS app for a day or so already, trying to solve an EXC_BAD_ACCESS (SIGSEGV) crash.
Here's the interesting part of the crash log:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x00000051
Triggered by Thread: 0
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x38bfc6e4 __kill + 8
1 myApp 0x002e3ca0 CLSSignalHandler + 192
2 libsystem_platform.dylib 0x38c61060 _sigtramp + 40
3 UIKit 0x306416a2 -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 310
4 UIKit 0x306417d0 __85-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]_block_invoke + 104
5 UIKit 0x306416e2 -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 374
6 UIKit 0x30641af2 -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:] + 30
7 UIKit 0x308d84b8 __UIViewWasRemovedFromSuperview + 184
8 UIKit 0x30640bae -[UIView(Hierarchy) removeFromSuperview] + 266
9 UIKit 0x30643402 -[UIView dealloc] + 362
10 CoreFoundation 0x2de00650 CFRelease + 552
11 CoreFoundation 0x2de0bb40 -[__NSArrayM dealloc] + 152
12 libobjc.A.dylib 0x38649b06 objc_object::sidetable_release(bool) + 170
13 libobjc.A.dylib 0x3863b002 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 354
14 CoreFoundation 0x2de0397c _CFAutoreleasePoolPop + 12
15 UIKit 0x3063b248 _wrapRunLoopWithAutoreleasePoolHandler + 32
16 CoreFoundation 0x2de9b1ca __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 18
17 CoreFoundation 0x2de98b6c __CFRunLoopDoObservers + 280
18 CoreFoundation 0x2de98eae __CFRunLoopRun + 726
19 CoreFoundation 0x2de03c22 CFRunLoopRunSpecific + 518
20 CoreFoundation 0x2de03a06 CFRunLoopRunInMode + 102
21 GraphicsServices 0x32af727e GSEventRunModal + 134
22 UIKit 0x306a7044 UIApplicationMain + 1132
23 myApp 0x000c4640 main (main.m:14)
24 myApp 0x000ac31c start + 36
Unfortunately NSZombieEnabled was unhelpful because the crash didn't happen anymore when it was set.
From my research I found that:
- it probably came from an object being released twice (presence of Release and AutoRelease stuff in the log)
- NSZombie objects don't log anything when they receive a
release
message
After narrowing down the source of the problem to 1 class, I looked at the allocation and deallocation of variables and properties. I found this in viewDidLoad
:
MyView *view = [[MyView alloc] initWithFrame:CGRectMake(...)];
[_tableView addSubview:view]; // _tableView is an outlet variable
_refreshHeaderView = view; // _refreshHeaderView is a class variable, not a property
[view release];
and in viewDidUnload
:
[_refreshHeaderView release];
_refreshHeaderView = nil;
I changed _refreshHeaderView = view;
by _refreshHeaderView = [view retain];
and now the app doesn't crash anymore.
I'm not so sure this is the correct solution, although the crash doesn't happen anymore, so that's why I have these questions:
- my understanding of what's happening is:
view
is initialized, its RC=1view
is added as a subview of_tableView
RC=2_refreshHeaderView
points to the same object thanview
view
is released RC=1- when the dealloc process starts,
_tableView
will releaseview
RC=0 - when
_refreshHeaderView
is released, app crashes - is it correct?
- why does the crash log show autorelease stuff although it's not used with my variables?
- is it true that NSZombies don't log any error when they receive a release message?
- which one is better ?
_refreshHeaderView = [view retain];
and[_refreshHeaderView release];
or_refreshHeaderView = view;
and NOT[_refreshHeaderView release];
Thanks for the help.