EXC_BAD_ACCESS in a UIScrollView

After using my latest iPhone application on a device for a while, I was getting the following crash:

Program received signal:  “EXC_BAD_ACCESS”.
(gdb) backtrace
#0  0x33369ebc in objc_msgSend ()
#1  0x320e5248 in -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded] ()
#2  0x338b4a14 in -[NSObject performSelector:withObject:] ()
#3  0x320e5098 in -[UIAnimator stopAnimation:] ()
#4  0x320e4b7c in -[UIAnimator(Static) _advance:] ()
#5  0x320e4a34 in LCDHeartbeatCallback ()
#6  0x34350e60 in HeartbeatVBLCallback ()
#7  0x332e91c0 in IOMobileFramebufferNotifyFunc ()
#8  0x316532f8 in ?? ()
#9  0x33866b50 in __CFMachPortPerform ()
#10 0x338ae52a in CFRunLoopRunSpecific ()
#11 0x338adc1e in CFRunLoopRunInMode ()
#12 0x3434e1c8 in GSEventRunModal ()
#13 0x32002c30 in -[UIApplication _run] ()
#14 0x32001230 in UIApplicationMain ()
#15 0x00002ff8 in main (argc=1, argv=0x2ffff550) at /Developer/svn/MyCompany/iPhone/MyApplication/Other Sources/main.m:14

As you can see from the trace, the only mention of my code in there is the call to main.

I ran Build and Analyze from Xcode, and also set it up to run the clang analyzer on my project from the Terminal, and both of these did not find any problems in the code.

After using the NSZombieEnabled flag in the application, it came up with this message in the console:

2010-09-11 17:10:33.970 MyApplication[9321:207] ***
-[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7489480

I think we finally tracked down a way to keep the error from occurring. I am guessing that the view was being deallocated and released while it was still undergoing a scroll animation. I changed my code to be like this:

[myTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:mainSection]
        animated:NO scrollPosition:UITableViewScrollPositionMiddle];

The application has not crashed with the same error since I changed all of these selectRowAtIndexPath calls to use the NO flag for the animated property. True, this does not fix the problem, but at this point, hiding it was good enough for me and our complaining customers.

2 Comments

  1. malex says:

    At first, *delegates* should be of *weak/assign* type. But event in this case there is a very common
    subtle obstacle driven by scroll animations. If you use animated content offset changes for
    your *ScrollViews* you strongly need to set its *delegate* to *nil* at *dealloc* method.

    Otherwise you will get the following

    [YourViewController respondsToSelector:]: message sent to deallocated instance

    The very common example:

    1. _tableView is ivar of YourViewController
    2. _tableView.delegate = self;
    3. – (void)scrollViewDidScroll:(UIScrollView *)scrollView is implemented at YourViewController
    4. at some point you call [_tableView scrollToRowAtIndexPath:indexPath
    atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    or [_tableView setContentOffset:CGPoint animated:YES]
    and try to close YourViewController

    The _tableView is retained by CoreAnimation, but YourViewController is deallocated!

  2. BP says:

    Thanks for the info, I went through my code and made a few tweaks based on your suggestion. We shall see if it causes my crash counts to go down.

    BP

Leave a Reply