Exception Types in iOS crash logs - iphone

I've seen a few different types of crash logs since I begin learning iOS development.
I know that:
Exception Type: EXC_BAD_ACCESS (SIGSEGV) mean we are accessing a released object.
but don't know about:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Type: EXC_CRASH (SIGABRT)
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Do you know how many Exception Types in iOS crash logs and what do they mean?

I know that: Exception Type: EXC_BAD_ACCESS (SIGSEGV) mean we are accessing a released object.
No.
A SIGSEGV is a segmentation fault, meaning you are trying to access an invalid memory address.
Those exceptions (in fact, they are signals) are not related to Objective-C, but C.
So you can get such an exception without Objective-C objects.
Note that a signal is not an exception, meaning you can't catch them with #try and #catch blocks.
You may set a signal handler with the signal and sigaction functions. Keep in mind some signals, like SIGABRT cannot be blocked.
You can check the Wikipedia page about signals, if you want more informations.
That said, to resume:
SIGSEGV (Segmentation fault)
Access to an invalid memory address. The address exist, but your program does not have access to it.
SIGBUS (Bus error)
Access to an invalid memory address. The address does not exist, or the alignment is invalid.
SIGFPE (Floating point exception)
Invalid arithmetic operation. Can be related to integer operations, despite the name.
SIGPIPE
Broken pipe.
SIGILL
Illegal processor instruction.
SIGTRAP
Debugger related
SIGABRT
Program crash, not related to one of the preceding signal.

SIGSEGV literally means you're accessing an address you don't own. So it's not necessarily that you're accessing a released object; you could be accessing an object that never existed, as in:
UIView *view; // uninitialised, could point to anything
[view setFrame:someFrame];
Or even just making an error in C-level non-object stuff, such as:
int array[100];
array[1000] = 23; // out-of-bounds access
SIGBUS is very similar to SIGSEGV, the difference being at the hardware level (usually the difference between trying to access an address that does exist but which you don't own and trying to access an address that doesn't have anything behind it, but that's not a strict definition), but is usually associated with the same sort of errors, though a SIGBUS is much more likely to be to do with an uninitialised variable than a SIGSEGV.
If you're trying to map to errors you probably made in Objective-C, you probably just want to read SIGSEGV and SIGBUS together as meaning "a memory access I didn't have the right to make".
SIGABRT is a program attempting to abort itself, so it usually means that some sort of internal consistency check has failed. For example, SIGABRT is raised if you try to free the same memory twice, or — at the Cocoa level — if you raise an NSException that isn't caught. If you get a SIGABRT, you've done something wrong that is detected by the system software (in contrast to SEGV and BUS, which arise in hardware).
SIGTRAP is a call out from the program to a debugger. Anecdotally, Apple seem to use these when you do something wrong that can be detected in software but relates to the environment rather than your specific code. So, for example, you call a C function that exists in the SDK you built with but not on the device you are running on (such as when you build against the latest SDK with a lower deployment target), or do a similar thing with an object.

These messages are from gdb, and they are not exclusive for objective-C.
To get info about the signals all you have to do is enter info signals at the debugger console, this is an example output. Sorry for no posting it here, but the format of the console output is awful.
Source and more info about signals

I've recently studied this topic area and here is my summary:
EXC_BAD_ACCESS (SIGSEGV) or
EXC_BAD_ACCESS (SIGBUS)
Our program most likely tried to access a bad memory location or the address was good but we did not have the privilege to access it. The memory might have been deallocated due to memory pressure.
EXC_BREAKPOINT (SIGTRAP)
This is due to an NSException being raised (possibly by a library on our behalf) or _NSLockError or objc_exception_throw being called. For example, this can be the Swift environment detecting an anomaly such as force unwrapping a nil optional.
EXC_BAD_INSTRUCTION (SIGILL)
This is when the program code itself is faulty, not the memory it might be accessing. This should be rare on iOS devices; perhaps a compiler or optimizer bug, or faulty hand written assembly code. On Simulator, it is a different story as using an undefined opcode is a technique used by the Swift runtime to stop on access to zombie objects (deallocated objects).
EXC_GUARD
This is when the program closed a file descriptor that was guarded. An example is the SQLite database used by the system.

Related

Segmentation fault from outside of my code

I have a wxWidgets/GTK based application that works well - except for one installation on an Debian Squeeze ARM system. There it crashes when the user just activates the main window of it. To find the reason for that I added a signal handler to the application and use libunwind out of that signal handler to find the source for the crash. During a test that worked fine, when the software writes e.g. to address 0x0 libunwind correctly points me to the function where that happens.
But the results for the system where the crash appears unexpectedly are a bit strange, they seem to happen outside of my application. One crash comes from a function with no name (here libunwind returns an empty string), and one is caused by "malloc_usable_size", a system function which should never die this way.
So...what to do next? All ideas, suggestions or any other hints are welcome since I'm not sure how to contunue with that problem...
Check for buffer overrun or overwriting some memory unexpectedly for any structures, pointers, memory locations for items returned by library functions.
Check for invalid pointer frees in your code for the library allocated pointers that you are using.
May be using valgrind would also help.

Exception handling in entire application

I have a few doubts regarding exception handling in iPhone. Here are they:
Suppose I have a chain of methods which are being called one after the other, that is, method A calls method B, which in turn calls method C, which calls method D. Which is the best place to put my try-catch block (is it method A or B or C or D or all of them). Also, I need to display an alert to user that an exception has occured and then, I want to log this exception to my server. So, if I am writing my try - catch block in all of this methods and if an exception occurs in method D; then I think the alert will be displayed 4 times and the web service for logging will also be called 4 times (till control reaches to catch block of method A). So, should I just use #throw; in catch block of method B, C and D and write my logic in catch block of method A (top level method) or should I avoid writing try - catch at all in methods B,C and D.
I need some sort of error code from the exception (because my web service needs parameters error-code and description). Is it possible to convert an exception to error or will I need to hard-code this code?
I had read somewhere about NSSetUncaughtExceptionHandler. And I think, if I can set this handler (in appDidFinishLaunching method of app delegate) and in the handler method, if I show to user some alert and call the web service; then I need not write try - catch block in each of my methods, in each of my classes. Am I right??
If an exception has occured and I have written either a try - catch block or NSSetUncaughtExceptionHandler, then will my app continue running or it will not respond to any of the user events. (I am sure it will handle the crash. What I want to know is whether it will hang)
Someone please enlighten me on this EXCEPTION TOPIC.
0) Avoid exceptions in Cocoa. They are generally non-recoverable. You might catch them for your own error reporting, but it's generally unsafe to assume you can recover from them.
1) If you need to catch, catch it immediately. Don't write your own throws -- instead, convert it to something like an NSError and pass that around. NSError can contain all the information you need to display or send an error code as well as a localized message.
2) You cannot convert an NSException into an NSError (directly) because an NSException does not have all the properties an NSError has - it is a different data representation. For one, an error code is not available. Two, the description is not localized. The best you can do is to create an error code and domain, then use the properties you need from the NSException and store that in an NSError. This could look something like the following:
// error checking omitted
extern NSString* const MONExceptionHandlerDomain;
extern const int MONNSExceptionEncounteredErrorCode;
NSError * NewNSErrorFromException(NSException * exc) {
NSMutableDictionary * info = [NSMutableDictionary dictionary];
[info setValue:exc.name forKey:#"MONExceptionName"];
[info setValue:exc.reason forKey:#"MONExceptionReason"];
[info setValue:exc.callStackReturnAddresses forKey:#"MONExceptionCallStackReturnAddresses"];
[info setValue:exc.callStackSymbols forKey:#"MONExceptionCallStackSymbols"];
[info setValue:exc.userInfo forKey:#"MONExceptionUserInfo"];
return [[NSError alloc] initWithDomain:MONExceptionHandlerDomain code:MONNSExceptionEncounteredErrorCode userInfo:info];
}
#catch (NSException * exc) {
NSError * err = NewNSErrorFromException(exc);
...
}
If the APIs you use throw exceptions you are expected to catch and recover from (e.g. not truly exceptional cases), then yes, you could catch and attempt to continue. Unfortunately, anybody that writes exceptions in Cocoa with the intent that you will catch them probably does not understand the issues well enough to implement a solid unwind implementation (e.g. even if it produces leaks, it's not solid).
3) That's really not the time or place to display an alert. If you install a top level exception handler (via NSSetUncaughtExceptionHandler) - You should simply log a message -- then the exception handler will abort. Your app is in an unstable state -- continuing is worse than aborting. You may want to send these custom messages home, it's best to do so at the next launch of your app.
4) In the majority of cases, your app is in an unstable state and you should not continue. But, to actually answer it for those corner cases: "Yes, you can recover and continue when you catch, but you should only attempt to recover and continue when the throwing API states that recovery is supported. If the problem is beyond your control, and the problem is not exceptional (e.g. file not found), and the vendor really expects you to continue, then I would have to assume that they expect you to continue, even though it really isn't (100% safe).". Do not attempt to recover/continue from within your top level exception handler (the program will abort after it returns). If you want to be very fancy and present that immediately on OSX, another process would be best. If you are calling through a pure C++ interface, then the unwinding is well defined, and the need to catch is necessary - do continue if it is recoverable. Exceptions in C++ can be recoverable and well defined - they are also used quite extensively (including less than exceptional conditions).
(IMO...) Exceptions in ObjC should not have been introduced, and any method that throws from system or third party libraries should be deprecated. They don't unwind well, or in a well defined manner. As well, unwinding flows against normal Cocoa program flow. That means that touching any objc object's memory/relations that was in mutation at the time of the throw and which lies between the throw and the catch is as good as undefined behaviour. Problem is - you have no idea what that memory is (in most cases, and within reasonable maintenance time). C++ exceptions are well defined, and they unwind correctly (e.g. destructors are called) - but trying to continue in an ObjC context is ignoring any consequences of undefined behavior. IMO, they should only exist for ObjC++ (because C++ requires them).
In an ideal world, your ObjC programs and the libraries you use would not use exceptions (at all). Since you use libraries that do throw (including Cocoa), install a top level exception handler only if you need some special information about the error. Where the API mandates that you could expect an exception thrown due to circumstances beyond your control and you are expected to recover, then write a catch but immediately convert that logic to normal program flow (e.g. NSError) - you never need to write your own throw. -[NSArray objectAtIndex: and "object does not respond to selector" are examples of programmer errors - they should not be caught, but the program should be corrected.

Usage of NSException in iPhone Apps

One of my friends asked me not to use NSException in iPhone Apps. The reason he gave was "performance bottleneck". But I am not convinced of it.
Can someone confirm me that we should restrain from using NSException in iPhone App? If you have best practices for using NSException, please provide that too.
UPDATE:
This link requests us to use Exception handling at the app level. Have someone ever done it? Please give the advantages of it and any other performance hitches it could create.
In short:
Do not use exceptions to indicate anything but unrecoverable errors
It is only appropriate to use #try/#catch to deal with unrecoverable errors. It is never appropriate to use #throw/#try/#catch to do control-flow like operations on iOS or Mac OS X. Even then, consider carefully whether you are better off using an exception to indicate an unrecoverable error or simply crashing (call abort()); a crash often leaves behind significantly more evidence.
For example, it would not be appropriate to use for catching out-of-bounds exceptions unless your goal is to catch them and somehow report the error, then -- typically -- crash or, at the least, warn the user that your app is in an inconsistent state and may lose data.
Behavior of any exception thrown through system framework code is undefined.
Can you explain the "Behavior of any
exception thrown through system
framework code is undefined." in
detail?
Sure.
The system frameworks use a design where any exception is considered to be a fatal, non-recoverable, error; a programmer error, for all intents and purposes. There are a very limited number of exceptions (heh) to this rule.
Thus, in their implementation, the system frameworks will not ensure that everything is necessarily properly cleaned up if an exception is tossed that passes through system framework code. Sine the exception is, by definition, unrecoverable, why pay the cost of cleanup?
Consider this call stack:
your-code-1()
system-code()
your-code-2()
I.e. code where your code calls into system code which calls into more of your code (a very common pattern, though the call stacks are obviously significantly deeper).
If your-code-2 throws an exception, that the exceptions passes over system-code means the behavior is undefined; system-code may or may not leave your application in an undefined, potentially crashy or data-lossy, state.
Or, more strongly: You can't throw an exception in your-code-2 with the expectation that you can catch and handle it in your-code-1.
I've used exception handling for my fairly intensive audio app with no problems whatsoever. After much reading and a bit of benchmarking and disassembly analysis, I've came to the controversial conclusion that there is no real reason not to use them (intelligently) and plenty of reason not to (NSError pointer-pointers, endless conditionals...yuck!). Most of what people are saying on the forums is just repeating the Apple Docs.
I go into quite a bit of detail in this blog post but I'll outline my findings here:
Myth 1: #try/#catch/#finally is too expensive (in terms of CPU)
On my iPhone 4, throwing and catching 1 million exceptions takes about 8.5 seconds. This equates to about only 8.5 microseconds for each. Expensive in your realtime CoreAudio thread? Maybe a bit (but you'd never throw exceptions there would you??), but an 8.5μs delay in the UIAlert telling the user there was a problem opening their file, is it going to be noticed?
Myth 2: #try Blocks Have a Cost On 32bit iOS
The Apple docs speak of "zero-cost #try blocks on 64bit" and state that 32 bit incurs a cost. A little benchmarking and disassembly analysis seems to indicate that there is zero-cost #try blocks on 32bit iOS (ARM processor) as well. Did Apple mean to say 32bit Intel?
Myth 3: It Matters that Exceptions Thrown Through Cocoa Frameworks are Undefined
Yes, they are "undefined", but what are you doing throwing through the Apple framework anyway? Of course Apple doesn't handle them for you. The whole point of implementing exception handling for recoverable errors is to handle them locally - just not every-single-line "locally".
One edge case here is with methods like NSObject:performSelectorOnMainThread:waitUntilDone:. If the later parameter is YES, this acts like a synchronous function in which case you might be forgiven for expecting the exception to bubble up to your calling scope. For example:
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////
#interface l5CCThread : NSThread #end
#implementation l5CCThread
- (void)main
{
#try {
[self performSelectorOnMainThread:#selector(_throwsAnException) withObject:nil waitUntilDone:YES];
} #catch (NSException *e) {
NSLog(#"Exception caught!");
}
}
- (void)_throwsAnException { #throw [NSException exceptionWithName:#"Exception" reason:#"" userInfo:nil]; }
#end
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////
#implementation l5CCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
l5CCThread *thd = [[l5CCThread alloc] init];
[thd start];
return YES;
}
// ...
In this case the exception would pass "through the cocoa framework" (the main thread's run loop) missing your catch and crashing. You can easily work around this using GCD's dispatch_synch and putting in it's block argument the method call plus any exception handling.
Why Use NSException's over NSError's
Anyone who's ever done work in one of the older C-based frameworks like Core Audio knows what a chore it is checking, handling and reporting errors. The main benefit #try/#catch and NSExceptions provides is to make your code cleaner and easier to maintain.
Say you have 5 lines of code which work on a file. Each might throw one of, say, 3 different errors (eg out of disk space, read error, etc.). Instead of wrapping each line in a conditional which checks for a NO return value and then outsources the NSError pointer investigation to another ObjC method (or worse, uses a #define macro!), you wrap all 5 lines in a single #try and handle each error right there. Think of the lines you'll save!
By creating NSException subclasses, you can also easily centralise error messages, and avoid having your code littered with them. You can also easily distinguish your app's "non-fatal" exceptions from fatal programmer errors (like NSAssert). You can also avoid the need for the "name" constant (the subclass's name, is the "name").
Examples of all this and more details about the benchmarks and disassembly are on this blog post...
Exceptions plus try/catch/finally is the paradigm used by pretty much every other major language (C++, Java, PHP, Ruby, Python). Maybe its time to drop the paranoia and embrace it as well...at least in iOS.
Generally ask yourself if you're trying to signal an error, or do you actually have an exceptional condition? If the former, then it's a very bad idea regardless of any performance issue, real or perceived. If the latter, it's most definitely the right thing to do.

Try-catch exception handling practice for iPhone/Objective-C

Apologies if this question has already been answered somewhere else, but I could not find any decisive answer when searching on it:
I'm wondering when try-catch blocks are to be used in objective-c iPhone applications. Apple's "Introduction to the Objective-C Programming Language" state that exceptions are resource intensive and that one should "not use exceptions for general flow-control, or simply to signify errors." From reading a few related questions here I also gather that people are not often using this method in practice.
So I guess the question is: what are the situations when it's appropriate to use try-catch blocks when developing for iPhone/Objective-C and when should they absolutely NOT be used?
For example, I could use them to catch beyond bounds and other exceptions when working with objects in arrays. I have a method which performs are few tasks with objects that are passed on in a number of arrays. The method returns nil if an error has occurred and a try-catch block could help me catch exceptions. However, I could of course simply write little if-tests here and there to ensure that I, for instance, never try to access an index beyond an arrays bounds. What would you do in this situation?
Thanks a lot!
It is only appropriate to use #try/#catch to deal with unrecoverable errors. It is never appropriate to use #throw/#try/#catch to do control-flow like operations.
In particular, it would not be appropriate to use for catching out-of-bounds exceptions unless your goal is to catch them and somehow report the error, then -- typically -- crash or, at the least, warn the user that your app is in an inconsistent state and may lose data.
Behavior of any exception thrown through system framework code is undefined.
Your if-test to do bounds checking is a far more appropriate solution.
#bbum's answer is absolutely correct (and he would know the answer better than most). To elaborate a bit...
In Cocoa, you should generally avoid using exceptions (#try/#catch[/#finally]) for flow control. As you mention, exceptions carry an unusually large cost (compared to run-times such as JVM or the CLR optimized for exception use). Furthermore, most of the Cocoa frameworks are not exception safe. Thus, throwing an exception through Cocoa framework code is dangerous and will likely cause odd, difficult to diagnose, and catastrophic (think possible data loss) bugs in your app.
Instead of using exceptions, Cocoa code uses NSError to signal error conditions that are recoverable within the application. Exceptions are used to signal conditions from which your application cannot recover. Thus a UI component requesting an out-of-bounds position in a model array could be signaled with an error (presented to the user with a reason their request could not be completed) while attempting to access an out-of-bounds position given an index that you think should be valid signals an exceptional condition where you app is in an inconsistent state and should probably die as soon as possible before it can do more damage.
NSParameterAssert, for example signals with an NSException when an assertion fails.
So when should you use exceptions or #try/#catch? If you're using a C/C++ library that makes use of exceptions, you should catch those exceptions before they can get thrown back through Cocoa code. Similarly, if you are serious about consistency of state within your application, you should raise an exception as soon as you detect that your state is inconsistent (and unrecoverable).

Matlab: getting "Unexpected error status flag encountered. Resetting to proper state"

I have a matlab script, that every now and them produces the message:
Caught std::exception Exception message is:
bad allocation
Unexpected error status flag encountered. Resetting to proper state.
What could be causing this?
This is a bug in MATLAB, in which some part of MATLAB is not handling a std::bad_alloc exception correctly (std::bad_alloc is an out-of-memory exception thrown from the C++ runtime library).
The "Unexpected error status flag encountered. Resetting to proper state." is an internal diagnostic - you shouldn't see it unless MATLAB has gotten into a bad state, which in this case is happening because it's encountering the bad_alloc someplace where it was not expected. Recent versions of MATLAB have fixed most of these issues, except in extremely low-memory situations (like, there's less than 1 kilobyte of free memory left). What version are you using?
My best guess is that your script is trying to allocate some memory and failing. The occurrence of such an error will depend on the availability of memory on your computer at the time allocation is attempted. The available memory will vary according to what is going on at the time in other programs, the operating system, even the state of your Matlab session.
For a more accurate diagnosis, you'll have to tell us more, maybe even post your script.
It was happening to me, and it turned out I had too many files open. fclose('all') set everything back to normal, and I made sure that all my fopen were followed by fclose.