Xcode 4.2 debug doesn't symbolicate stack call

2019-01-01 09:38发布

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.

9条回答
看淡一切
2楼-- · 2019-01-01 10:08

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

查看更多
长期被迫恋爱
3楼-- · 2019-01-01 10:14

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)

查看更多
裙下三千臣
4楼-- · 2019-01-01 10:17

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.

查看更多
栀子花@的思念
5楼-- · 2019-01-01 10:17

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
查看更多
梦该遗忘
6楼-- · 2019-01-01 10:20

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.

查看更多
冷夜・残月
7楼-- · 2019-01-01 10:23

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)
查看更多
登录 后发表回答