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:
release
messageAfter 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:
view
is initialized, its RC=1view
is added as a subview of _tableView
RC=2_refreshHeaderView
points to the same object than view
view
is released RC=1_tableView
will release view
RC=0_refreshHeaderView
is released, app crashes_refreshHeaderView = [view retain];
and [_refreshHeaderView release];
or_refreshHeaderView = view;
and NOT [_refreshHeaderView release];
Thanks for the help.
Your summary in point 1 looks correct to me.
Don't confuse AutoReleasePools with ARC - AutoReleasePools are like the garbage collector in Java. You can explicitly create an AutoReleasePool if you want but there is always an implicit pool established with the run loop. Migrating to ARC may require code changes (and does require different use of AutoRelease).
Information on NSZombies is in this answer. Essentially you should get a log if you release an NSZombie with a reference count of 0. I am not sure why you weren't seeing the warning.
_refreshHeaderView = [view retain]; and [_refreshHeaderView release];
is better because your object is holding a reference to the object, so it needs to manage the reference count.
User contributions licensed under CC BY-SA 3.0