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.

1
  • 2
    Better is to use a property, which will manage memory for you and use self.refreshHeaderView = nil; in dealloc. Better still use ARC...
    – trojanfoe
    Mar 20, 2014 at 7:51

1 Answer 1

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.

9
  • That's better than using a getter/setter?
    – trojanfoe
    Mar 20, 2014 at 7:58
  • It is the better of the two options proposed. As you suggest ARC is probably the best solution, but it may be non-trivial to modify an existing project
    – Paulw11
    Mar 20, 2014 at 8:02
  • You don't have to stay within the confines of the two choices provided by the OP, if a better, third, option exists. In this case there is a better option.
    – trojanfoe
    Mar 20, 2014 at 8:03
  • Yes, but it may involve significant changes to their existing code base after effort has already been expended on finding the bug in the first place
    – Paulw11
    Mar 20, 2014 at 8:05
  • That's true; however that's not really something you should worry about.
    – trojanfoe
    Mar 20, 2014 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.