142

I have a problem with Xcode 4.2 debugging in an iOS 5 simulator/device. The following code crashes, as expected:

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

In iOS 4, I get a useful stack trace of hex numbers. But in iOS 5, it just gives me:

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

Thanks.

WiseOldDuck
  • 3,156
  • 2
  • 24
  • 27
cekisakurek
  • 2,474
  • 2
  • 17
  • 28

9 Answers9

259

Nothing I tried would fix this (tried both compilers, both debuggers, etc.) After upgrading XCode for the iOS 5 update, no stack traces seemed to work.

However, I have found an effective work-around - creating my own exception handler (which is also useful for other reasons). First, create a function that will handle the error and output it to the console (as well as whatever else you want to do with it):

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

Next, add the exception handler to your app delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

That's it!

If this doesn't work, then there are only two possible reasons:

  1. Something is overwriting your NSSetUncaughtExceptionHandler call (there can be only one handler for your entire app). For example, some 3rd party libraries set their own uncaughtExceptionHandler. So, try setting it at the END of your didFinishLaunchingWithOptions function (or selectively disabling 3rd party libraries). Or better yet, set a symbolic break point on NSSetUncaughtExceptionHandler to quickly see who is calling it. What you may want to do is to modify your current one rather than adding another one.
  2. You're not actually encountering an exception (for example, EXC_BAD_ACCESS is not an exception; credit to @Erik B's comments, below)
Zane Claes
  • 14,732
  • 15
  • 74
  • 131
  • 1
    Glad to hear it :) I find it to be useful to write the crash log to a file and prompt the user to submit it on the next launch (in release mode only, to not get in the way of debugging). This lets me get great bug reports... and the users know that their problem is being addressed :) – Zane Claes Oct 25 '11 at 23:32
  • Is there a reason apple changed this behavior? I am so happy you offered a remedy. – Jesse Black Nov 01 '11 at 04:47
  • 2
    This doesn't seem to work -- the `uncaughtExceptionHandler` routine is never invoked. – Hot Licks Nov 16 '11 at 16:32
  • correct. this does help finding out the hidden issue behind SIGABRT . – Raptor Nov 21 '11 at 06:32
  • 1
    Can you please be more specific on how to use it? It doesn't seem to work for me. – Dani Pralea Dec 17 '11 at 16:34
  • OH MY GOSH! This just may be the greatest day of my life. @ZaneClaes I forever bow at your feet. You have no idea how much this bugged me about XCode. Thankyou. – mtmurdock Mar 13 '12 at 16:30
  • +1 That's great work man. Helped me find a bug I wasn't able to solve otherwise :) – Niko Apr 20 '12 at 10:17
  • This solution doesn't seem to work. And I know I have an exception, because WiseOldDuck's answer worked for me. I see that it worked for others, so I know it's a good answer – Nicu Surdu Apr 27 '12 at 16:32
  • 1
    Pretty sad xCode doesnt display this for us. – Authman Apatira Jul 21 '12 at 00:22
  • Very, very nice. BTW to anyone who this may help, if you have an exception breakpoint set also, you will still need to press continue a few times before it prints the stack trace. – Patrick Pijnappel Jul 26 '12 at 12:55
  • 1
    Much appreciated! It's baffling that Apple doesn't implement this kind of rudimentary functionality into the IDE. – devios1 Mar 08 '13 at 18:10
  • I wish I could give some more +1s. Thanks a lot – rptwsthi Apr 09 '13 at 11:45
  • 1
    @HenrikErlandsson `EXC_BAD_ACCESS` is not an uncaught exception. You get `EXC_BAD_ACCESS` when you try to access memory that isn't yours. Usually because you're trying to use an object that has already been released. `NSZombie` should help you with that. – Erik B May 27 '13 at 14:17
  • 1
    @Erik B If not an exception in the OS code that isn't handled, what is it then? – Henrik Erlandsson May 28 '13 at 08:16
  • @ZaneClaes: Please can you add swift version also & where to add and call above mentioned method? – Abhishek Thapliyal Sep 10 '18 at 12:08
  • @AbhishekThapliyal this question is 5+ years old and I stopped doing mobile dev before Swift even came out. But, all of the functions here are the most basic iOS SDK functions that have existed since the earliest (public) iOS. If you just google them, you'll find tons of official Swift documentation on them. – Zane Claes Sep 15 '18 at 19:26
110

There is a useful option of adding an Exception Breakpoint (using the + at the bottom of the Breakpoint Navigator). This will break on any Exception (or you can set conditions). I don't know if this choice is new in 4.2 or if I only finally noticed it trying to workaround the missing symbols problem.

Once you hit this breakpoint you can use the Debug Navigator to navigate the call stack, examine variables, etc as usual.

If you do want a symbolicated call stack suitable for copy/pasting or the like, gdb backtrace will work fine from there:

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(etc)

WiseOldDuck
  • 3,156
  • 2
  • 24
  • 27
  • 3
    This works perfectly for me so far. The debugger halts on the crashing line now, no need for the backtrace. – Tim Nov 03 '11 at 19:21
  • 1
    This perfectly works for me too. Thank you so much, I was going insane without this breakpoint... – William Denniss Dec 23 '11 at 08:56
  • +1 for it worked. It doesn't give you such a nice error message explaining the reason of the exception, but it's a start ... – Nicu Surdu Apr 27 '12 at 16:33
  • you are my HotD @WiseOldDuck. – Maverick1st May 23 '12 at 09:22
  • This restores expected behavior for me. **NOTE: Also remember to re-add this breakpoint on new projects!** – MechEthan Jul 16 '12 at 17:09
  • This used to work for me, but today it stopped working. XCode halted inside the Cocoa assembly code for objc_exception_throw, but there was nothing useful on the stack (and yes, I had the stack detail slider all the way to the right). However, Zane's answer above still works for me. So, if you run into this situation, you can try that. – Joe Strout Jul 30 '13 at 01:16
46

There is a new feature on the debugger. You can set a break point whenever a exception is thrown and stop the execution right there, just as it used to happen on 4.0.

On the "Breakpoint Navigator", add a "Exception Breakpoint" and just press "Done" on the options popup.

That's all!

PS: In some cases would be better to break only for Objective-C exceptions.

Pedro
  • 1,171
  • 11
  • 7
  • Definately this is the solution for me. – bradgonesurfing Nov 03 '11 at 19:53
  • This was the issue for me. A colleague and I share the same Xcode project and I asked him if he was having the problem, and he wasn't. The difference was that his project was breaking on objective-c exceptions (objc_exception_throw) – horseshoe7 Jan 10 '12 at 12:02
  • You just helped find an untraceable bug. Thank you so much. I have been looking everywhere for something like this. – rjgonzo Jul 27 '12 at 20:16
  • 1
    This works like a charm! That was exactly what I was looking for, this is better than adding the Exception Handler since adding the Breakpoint can take you right where the exception was thrown, the exception handler works but just give you an idea. – im8bit Aug 08 '12 at 07:00
21

Here is one more solution, not so elegant as previous, but if you didn't add exception breakpoints or handlers, it can be only one way to go.
When app crashes, and you get your raw first throw call stack (in hex numbers), type into Xcode console info line *hex (don't forget star and 0x hex specifier), for example:

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

If you are using lldb, you can type image lookup -a hex (without star in this situation), and you get similar output.

With this method, you can traverse from top of the throw stack (there will be about 5-7 system exception propagators) to your function which caused a crash, and determine exact file and line of code.

Also, for similar effect you can use atos utility in terminal, just type:

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

and you get symbolicated stack trace (at least for functions you have debug symbols). This method is more preferable, because you don't have for each adress call info line, just copy adresses from console output and paste them into terminal.

Alexander
  • 780
  • 1
  • 8
  • 22
9

You can add an Exception Breakpoint (using the + at the bottom of the Breakpoint Navigator) and add the action bt to it (click the Add Action button, select Debugger Command, enter "bt" in the text field). This will display the stack trace as soon as an exception is thrown.

MonsieurDart
  • 6,005
  • 2
  • 43
  • 45
6

At Xcode's debug console prompt type:

image lookup -a 0x1234

And it will show you something like:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
Matt Connolly
  • 9,757
  • 2
  • 65
  • 61
  • Thanks, I was really looking for this. Surprising there's no shortcut for displaying the entire "first throw call stack" as a call stack, for I guess a Python lldb script can be easily written. – Ilya Jun 08 '15 at 12:56
6

This is a common problem, not getting stack traces in 4.2. You can try swapping between LLDB and GDB to see if you get better results.

File a bug report here.

http://developer.apple.com/bugreporter/

EDIT:

I believe that if you swap back to LLVM GCC 4.2 you'll not see this happen. You may lose features you need though.

logancautrell
  • 8,762
  • 3
  • 39
  • 50
  • yes I tried switching the compilers, however the issue remains. but thanks anyways :) – cekisakurek Oct 20 '11 at 20:21
  • He suggested switching debuggers, not compilers. – bames53 Oct 25 '11 at 22:47
  • 1
    FYI: In this instance, it has nothing to do with the version of the compiler or debugger that you're using. This is a change in the console output from the iOS. – clarkcox3 Oct 31 '11 at 19:29
  • Interesting how much experiences of this vary - I think there are a few problems. I was not able to get the debugger to stop on the exception breakpoint. Switching from GDB to LLDB solved the problem. – Matt Jan 09 '12 at 06:18
6

Use this code in your main function:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int retVal;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException *exception) {
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    }
    @finally {
        [pool release];
    }
    return retVal;
}
Flexo
  • 87,323
  • 22
  • 191
  • 272
wilson lin
  • 61
  • 1
  • 2
  • This does not seem to work with storyboards. 2012-06-04 20:34:52.211 Problems[1944:207] The app delegate must implement the window property if it wants to use a main storyboard file. 2012-06-04 20:34:52.213 Problems[1944:207] Applications are expected to have a root view controller at the end of application launch – macasas Jun 04 '12 at 18:49
1

Turning 'Compile for Thumb' back on (debug configuration) worked for me.