How to know which line is causing exception? - ios

I am new to XCode and Objective C. I have intentionally make a mistake to assign number to NSString*.
NSString* s = #1;
[s uppercaseString];
Though XCode gives me warning, this code will compile. But at runtime I get exception. Now I see in logs, (Sorry for image, I was not able to paste is as text properly due to formatting)
In this log, how I find exact place of error. How this log tells me which code to change.

So it looks like you are running the Release build (debug symbols stripped) and if you got that crash log in a production environment you would need to symbolicate it in order to find the line.
This Apple TN gives some details of Symbolication.
In a development environment you would simply add an exception breakpoint and run it from Xcode, as the debug symbols would not be stripped.

To understand what line causes the problem, you usually need to add exception breakpoint to your project as explained in this document;
In the bottom-left corner of the breakpoints navigator, click the
Add button.
Choose Add Exception Breakpoint.
In the Exception pop-up menu, choose the type of exception on which
you want execution to stop:
All. Stops on all exceptions.
Objective-C. Stops on Objective-C exceptions.
C++. Stops on C++ exceptions. To stop on a particular C++ exception, specify the exception name.
Choose the phase of the exception handling process at which you want program execution to stop.
Click Done.

line 5 Sam : [BIDViewController viewDidLoad] + 143 , if this is a release build , you need to resolve with symbols the memory address of the function , this is called "symbolize" the crash dump...

In the log look for your project name and you will come to know.
e.g.
line 5 Sam : [BIDViewController viewDidLoad] + 143
If you want to produce real crash without warning, try following code it will produce index out of bound exception and will crash
NSArray *array = #[#"1",#"2"];
NSLog(#"Item not accessible->%#",(NSString*)array[2]);

set Exception breaking point or enable NSZombie object
or
NSZombie
From the menu bar, choose Project > Scheme > Edit Scheme

Related

XCode not stopping on breakpoint in method called from LLDB

XCode 7.2.1
iPad Retina iOS 9.2 Simulator
I have several breakpoints set in a particular class in an XCode project.
Everything I discuss below takes place in this one class file.
I set the breakpoints on -(int16_t)areaNbr by clicking in the gutter, and set no conditions or anything on them. I confirmed they existed as far as LLDB is concerned by running breakpoint list from the LLDB prompt.
The project scheme is set to build for debugging, not release.
I run the project in the simulator, and stop at a breakpoint in a different method than the one in question, at which time I want to go to the LLDB prompt and call po [self areaNbr] and step through areaNbr.
Please note, as this may be quite relevant, I have NO code in the project itself that calls
-(int16_t)areaNbr
Now, I CAN get this to stop at my breakpoints on -(int16_t)areaNbr if I add some code to the project that calls the method.
For example, if I add something like NSLog(#"... %d", [self areaNbr])
I know the issue has nothing to do with compiling away the method simply because nothing calls it, because if that were true, then my call to po [self areaNbr] wouldn't be spitting out the result to the debugger window as pictured below. So the method is being compiled, and certainly recognized as existing by the debugger for execution purposes... just not for stepping purposes.
FYI, [self area] is returning "Area01"
Calling breakpoint list in LLDB returns the following
By default, lldb does not stop at breakpoints in hand-called code. The majority of folks use expr & expr -O -- i.e. po to print values & objects and were annoyed if they stopped at breakpoints they had set for other purposes.
However, it is easy to control this behavior, just use:
(lldb) expr -i 0 -- [self areaNbr]
Then you will stop at your breakpoint.
In this example, I left out the -O which is the object printing part, since if you just want to call this method, you likely don't care about calling description on the result after the expression is evaluated.
You can see all the options for expression evaluation by doing:
(lldb) help expr

Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940)

I'm new to lldb and trying to diagnose an error by using po [$eax class]
The error shown in the UI is:
Thread 1: EXC_BREAKPOINT (code=EXC_i386_BPT, subcode=0x0)
Here is the lldb console including what I entered and what was returned:
(lldb) po [$eax class]
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940).
The process has been returned to the state before expression evaluation.
The global breakpoint state toggle is off.
You app is getting stopped because the code you are running threw an uncaught Mach exception. Mach exceptions are the equivalent of BSD Signals for the Mach kernel - which makes up the lowest levels of the macOS operating system.
In this case, the particular Mach exception is EXC_BREAKPOINT. EXC_BREAKPOINT is a common source of confusion... Because it has the word "breakpoint" in the name people think that it is a debugger breakpoint. That's not entirely wrong, but the exception is used more generally than that.
EXC_BREAKPOINT is in fact the exception that the lower layers of Mach reports when it executes a certain instruction (a trap instruction). That trap instruction is used by lldb to implement breakpoints, but it is also used as an alternative to assert in various bits of system software. For instance, swift uses this error if you access past the end of an array. It is a way to stop your program right at the point of the error. If you are running outside the debugger, this will lead to a crash. But if you are running in the debugger, then control will be returned to the debugger with this EXC_BREAKPOINT stop reason.
To avoid confusion, lldb will never show you EXC_BREAKPOINT as the stop reason if the trap was one that lldb inserted in the program you are debugging to implement a debugger breakpoint. It will always say breakpoint n.n instead.
So if you see a thread stopped with EXC_BREAKPOINT as its stop reason, that means you've hit some kind of fatal error, usually in some system library used by your program. A backtrace at this point will show you what component is raising that error.
Anyway, then having hit that error, you tried to figure out the class of the value in the eax register by calling the class method on it by running po [$eax class]. Calling that method (which will cause code to get run in the program you are debugging) lead to a crash. That's what the "error" message you cite was telling you.
That's almost surely because $eax doesn't point to a valid ObjC object, so you're just calling a method on some random value, and that's crashing.
Note, if you are debugging a 64 bit program, then $eax is actually the lower 32 bits of the real argument passing register - $rax. The bottom 32 bits of a 64 bit pointer is unlikely to be a valid pointer value, so it is not at all surprising that calling class on it led to a crash.
If you were trying to call class on the first passed argument (self in ObjC methods) on 64 bit Intel, you really wanted to do:
(lldb) po [$rax class]
Note, that was also unlikely to work, since $rax only holds self at the start of the function. Then it gets used as a scratch register. So if you are any ways into the function (which the fact that your code fatally failed some test makes seem likely) $rax would be unlikely to still hold self.
Note also, if this is a 32 bit program, then $eax is not in fact used for argument passing - 32 bit Intel code passes arguments on the stack, not in registers.
Anyway, the first thing to do to figure out what went wrong was to print the backtrace when you get this exception, and see what code was getting run at the time this error occurred.
Clean project and restart Xcode worked for me.
I'm adding my solution, as I've struggled with the same problem and I didn't find this solution anywhere.
In my case I had to run Product -> Clean Build Folder (Clean + Option key) and rebuild my project. Breakpoints and lldb commands started to work properly.

Xcode exception breakpoint doesn't print details of the exception being thrown

SUMMARY
When I set an exception breakpoint, I don't get the exception message. How do I get the exception message? I already know how to get the stack trace, but that doesn't include the exception message.
DETAILS
In the past I developed iOS Apps with Xcode and when there was a problem, I'd get an error/exception. The exception would often have a message like "can't dereference null" or whatever.
Now, using Xcode 4.6.x for the past several weeks I've never gotten an exception message. I'll often get a SIGABRT. I put in the break on exception breakpoint and it will break there, but it's off in some assembly within the iOS SDK and I never get a message.
In fact, I can't remember the last time I saw anything show up in the debugger console.
Did exception info dissappear with the migration to LLVM?
It's very frustrating to have my app just crash in the SDK without knowing why. I check the last function to make sure things are set up correctly (objects allocated, etc) and they are which means I'm left with no clues.
Is it possibly a build setting held over from the past is somehow turning off exception messages?
Please reopen question. It now has an answer!
In the comments an excellent answer has been given. This should be promoted to full answer, and so I can mark the question answered and others who have this common issue can find it. In order for that to happen, the question needs to be reopened! (I'll delete this plea after that happens.)
I will update Jeff's answer here:
To have both the line causing the exception highlighted (and not UIApplicationMain() in main.m) AND to see the reason for the exception (e.g., "error: A fetch request must have an entity."), do this:
In the Breakpoint navigator:
Add (+), Add Exception Breakpoint
Select the new breakpoint, Control-Click, Edit Breakpoint
Add Action
Enter: po $arg1
The relevant part of the stack trace will be in the nagivator area.
This seems to still work in Xcode 9
Here is my addition for use with Xcode 6 and below.
Enter: po (NSException*) $eax
In Xcode 6 you must explicitly provide the object type because it is no longer inferred.
For Xcode 7-9 (based off Jeff's answer):
In the Breakpoint navigator:
Add (+), Add Exception Breakpoint
Select the new breakpoint, Control-Click, Edit Breakpoint
Add Action
Enter: po $arg1
To have both the line causing the exception highlighted (and not UIApplicationMain() in main.m) AND to see the reason for the exception (e.g., "error: A fetch request must have an entity."), do this:
In the Breakpoint navigator:
Add (+), Add Exception Breakpoint
Select the new breakpoint, Contorl-Click, Edit Breakpoint
Add Action
Enter: po $eax
The relevant part of the stack trace will be in the nagivator area.
Yes xcode is not so friendly for debugging. I like this article which helps me to understand crash logs a bit clearly))
Demystifying iOS Application Crash Logs
Also do this if you see error "message sent to deallocated instance"
'Products -> Edit Scheme -> Enable Zombie Objects'
this will enable zombie objects and when you do profile to your project choose
"zombie", cause error and you will be able to see which objects was deallocated e.g NSArray *myArray
The information I get from po $eax or po (NSException *)$eax seems to be different from what Xcode would print if no exception breakpoints are set. So I do the following,
Add an exception breakpoint
Exception occurs, breakpoint was hit -> I know the location
Temporarily disable breakpoints (second button on the left in Debug area)
Continue program execution (third button on the left in Debug area)
Details are printed -> I know the cause
Obviously not very elegant and flexible, but at least I two big questions are answered (where and why).
You can use bt or thread backtrace command to print error trace
Show the stack backtrace for the current thread.
The same stack trace you can find in crash reports
Information about current thread use currentThread
//Objective-C
po [NSThread currentThread]
//Swift
po Thread.currentThread
*Sometimes you can use fr v(or just v from XCode 10.2) when po is not working

What am I missing about C++ exception breakpoints in Xcode 4.3?

I want to be able to specify a subset of all C++ exceptions for Xcode (lldb) to break upon. It looks like this is supported in the UI:
But for the life of me, I can't make it work. If I leave it set to the default "All C++ Exceptions", it works and every exception thrown triggers the breakpoint. If I attempt to specify an exception by name, the breakpoint is never triggered.
Has anyone else had issues with this, or is this just my problem?
Despite the UI, lldb is unable to set breakpoints on specific C++ exceptions or it does not resolve the name correctly.
I set a breakpoint for std::underflow_error and then using the lldb breakpoint list command, determined it only places a symbolic breakpoint on std::underflow_error:
9: name = 'std::underflow_error', locations = 0 (pending)
I suspect that lldb never resolves std::underflow_error to the constructor. C++ name mangling might have something to do with it too.
If you create a breakpoint for all C++ exception, you will see it creates a symbolic breakpoint on __cxa_throw:
10: name = '__cxa_throw', locations = 1, resolved = 1
10.1: where = libc++abi.dylib`__cxa_throw, address = 0x01cefa44, resolved, hit count = 0
You might be able to put a breakpoint in the constructor of the exception you are interested in, assuming it is instantiated and thrown at the same point.

Xcode 4.2 debug doesn't symbolicate stack call

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.
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:
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.
You're not actually encountering an exception (for example, EXC_BAD_ACCESS is not an exception; credit to #Erik B's comments, below)
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)
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.
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.
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.
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.
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;
}
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
Turning 'Compile for Thumb' back on (debug configuration) worked for me.

Resources