0

I was having trouble symbolicating some code in distribution build and finally created a simple project which has a button that basically causes a crash by accessing an objectAtIndex in an array that doesn't exist.

In release (or distribution) build the trace comes up like this when symbolicated where MyApp function calls are completely missing:

0- CoreFoundation                   0x34dcb29e __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x3537397a objc_exception_throw +26 
2   CoreFoundation                  0x34d16b70 -[__NSArrayM objectAtIndex:] + 160 
3   UIKit                           0x311a40a0 -[UIApplication endAction:to:from:forEvent:] + 68
4   UIKit                           0x311a4052 -[UIApplication sendAction:toTarget:fromSender:forEvent:]   + 26 
5   UIKit                           0x311a4030 -[UIControl sendAction:to:forEvent:] + 40     
6   UIKit                           0x311a38e6 -[UIControl(Internal) _sendActionsForEvents:withEvent:] +   498
...

In debug build it shows MyApp functions where the code causing the crash is:

0   CoreFoundation                  0x34dcb29e __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x3537397a objc_exception_throw + 26
2   CoreFoundation                  0x34d16b70 -[__NSArrayM objectAtIndex:] + 160
3   MyApp                           0x00098128 -[ViewController processArray] (ViewController.m:58)
4   MyApp                           0x0009814e -[ViewController Crash:](ViewController.m:63)**
5   UIKit                           0x311a40a0 -[UIApplication sendAction:to:from:forEvent:] + 68
6   UIKit                           0x311a4052 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26
7   UIKit                           0x311a4030 -[UIControl sendAction:to:forEvent:] + 40
8   UIKit                           0x311a38e6 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498

The above traces are off the device logs after performing identical tests of deploying and clicking on the button.

Several articles/blogs/questions on SO have talked about symbolication issues where hex symbols are shown instead of method name etc (which is different from this problem) and I've tried deleting stuff from derived data, cleaned out the build directory etc but this can be consistently reproduced. Can anyone please explain why this is happening.

EDIT: Adding the code for easy reference:

-(void) processArray
{
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@"One", @"Two", @"Three", nil];
    [array objectAtIndex:3];//Intentional crash for testing
}

- (IBAction)Crash:(id)sender 
{    
    [self processArray];
}
Truth
  • 13
  • 5
  • 1
    without giving us some code, I can only guess here, although it doesn't look like you are linking any external library, inside the Build Settings of your app, make sure you are including everything in Header Search Paths of both Debug and Release – kushyar May 24 '13 at 00:41
  • No, I am not linking any external libraries. The test app created is very simple. Add a button and action to it. Call a method that processes an array as follows: NSMutableArray *array = [NSMutableArray arrayWithObjects:@"One", @"Two", @"Three", nil]; [array objectAtIndex:3]; – Truth May 24 '13 at 01:21
  • Odd, I don't see any answers. Is it some SO permissions thing? Thanks for your help. – Truth May 24 '13 at 16:17
  • I removed the answer as another user pointed out that you are deliberately causing the crash by accessing an item that doesn't exist (objectAtIndex:3), I didn't realize that was intentional. – kushyar May 24 '13 at 16:23
  • Ok any ideas?.... Anyone? – Truth May 24 '13 at 17:32
  • can you give us more info? which version of xcode and iOS are you using/targeting? – kushyar May 24 '13 at 18:31
  • I upgraded to xcode 4.6.2 today hoping that solves the problem in some way. I was using Xcode 4.5 until yesterday. iOS v6.0.1 – Truth May 24 '13 at 20:35

1 Answers1

0

Try turning off compiler optimizations and reproducing the crash in the release build.

I suspect that you are getting bitten by a tail call optimization. The compiler may issue instructions that JMP directly from the end of your method to whatever method is called.

i.e. in this case:

 - (void)boo
 {
    [self bangAGong];
 }

Since there is no return value, etc... the compiler can rewrite the call to bangAGong such that it reuses the current stack frame. This is called tail calling (and is also how objc_msgSend() works. By doing this, it eliminates a pop of the frame on return.

This makes your code run slightly faster, but also means that it'll appear like stack frames are dropped from crash reports.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • Thanks! That's exactly what it was. I tested it by providing an intentional return value and the method started appearing in the stack trace. – Truth Jun 14 '13 at 23:31