Understanding the solution for a EXC_BAD_ACCESS (SIGSEGV) crash

1

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:

  1. my understanding of what's happening is:
    • view is initialized, its RC=1
    • view is added as a subview of _tableView RC=2
    • _refreshHeaderView points to the same object than view
    • view is released RC=1
    • when the dealloc process starts, _tableView will release view RC=0
    • when _refreshHeaderView is released, app crashes
    • is it correct?
  2. why does the crash log show autorelease stuff although it's not used with my variables?
  3. is it true that NSZombies don't log any error when they receive a release message?
  4. which one is better ?
    • _refreshHeaderView = [view retain]; and [_refreshHeaderView release]; or
    • _refreshHeaderView = view; and NOT [_refreshHeaderView release];

Thanks for the help.

ios
objective-c
asked on Stack Overflow Mar 20, 2014 by Philippe A

1 Answer

0

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.

answered on Stack Overflow Mar 20, 2014 by Paulw11 • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0