What is a Fatal error actually? - fatal-error

I wonder what Fatal error means. Why do they happen? Why do we see them in so much places? I saw them so many times, In Node.js, CS:GO and many places but why do they happen? A logical error or something in the code?

A fatal error is an error that causes a program to terminate without
any warning or saving its state. A fatal error, upon occurring, aborts
the application currently running, and may cause the user to lose any
unsaved changes made in the program. Exact reasons for fatal errors
are very difficult to determine.
A fatal error occurs when an application tries to access invalid data
or code, an illegal action is attempted or an infinity condition is
met. The program shuts down and returns the user to the operating
system. An operating system keeps a log of the information related to
the error for the user to view the details and determine possible
causes of the fatal error. Similarly, in some cases the image of a
process (core dump) is also sometimes maintained by the OS in the
event of a fatal error.

Related

How should you handle errors in a production environment?

I've been following along with some tutorials and have built an app that I'd like to publish, but I'm unsure how to deal with error handling.
Tutorials teach you about things like do-catch blocks but whenever they deal with the case where an error is thrown, they just log the error to console, which is obviously unhelpful in a production environment.
Moreover, some examples of the do-catch blocks appear to have little use. As an example, I'm using Realm Database as a core part of my app, and I'm told the way to initialise it is like so in the AppDelegate:
do {
_ = try Realm()
} catch {
// TODO: - Handle Exception
}
But in this case, since realm is a core part of my app, I wouldn't even mind if it crashed the app, because if it doesn't init properly it's going to crash later anyway.
There are obvious cases when I should just display an error to the user (e.g. If you're trying to connect to an API but there is no wifi), or where a default value could be provided, but I don't know what to do here.
There's no single good approach to handling errors, since how an error should be handled completely depends on the exact situation.
In general, however, there are some guidelines on error handling:
Use do-catch blocks on throwable functions unless you have a very
good reason to do so
Avoid runtime errors at all costs and don't throw fatal errors. Even if your app encounters an error that cannot be properly handled (the results of a throwable function is absolutely needed for your app to function), don't let your app crash due to a runtime error, rather let the user know that there's something wrong. A crashing application sends a very bad message to your users, while failing gracefully after encountering an error doesn't seem as bad.
In a catch block, try to solve the error without
letting the user know that there was an error if the error is
recoverable (for instance, you can use a default value instead of the
value you expected from the throwable function)
If the error can't be
handled, let the user know that there was an error (such as they
don't have internet connection when making a network request or a
network request failed for any other reason) and try to give them an
alternative approach (i.e. try later when you have internet
connection)
Only use try! and similar forced methods (force unwrapping, etc.) if you are absolutely sure that the function won't actually throw an error (for instance Realm.init() can only throw an error on the very first call to it in an app's lifecycle, so after the first instantiation of Realm, you can safely do try! Realm()) or if the error represent a programmer error (such as a file not being in the right place, which is needed for the application), but make sure you actually correct such errors in the development phase

How to intercept EXC_BAD_INSTRUCTION when unwrapping Nil

I am building some rudimentary crash logging system based on this blog post (Yes, I am aware of PLCRashReporter, and No, I can't use it and need to roll my own, however limited. Thank you).
My code registers both an exception handler (with NSSetUncaughtExceptionHandler()) and a signal handler for most signals:
SIGQUIT
SIGILL
SIGTRAP
SIGABRT
SIGEMT
SIGFPE
SIGBUS
SIGSEGV
SIGSYS
SIGPIPE
SIGALRM
SIGXCPU
SIGXFSZ
It seems to work fine with basic Objective-C stuff such as "unrecognized selector sent to instance...", etc.
Next, I tried it with the following Swift code:
var empty:String! = nil
let index = empty.startIndex // < KA-BOOM!
...but the thrown exception EXC_BAD_INSTRUCTION is not caught (my handler is not called), and instead I get the familiar:
fatal error: unexpectedly found nil while unwrapping an Optional value
...in the Xcode console.
What am I missing?
This answer says that this kind of runtime error can be handled with SIGTRAP; however I am already handling that signal and it doesn't seem to work.
ADDENDUM: It seems there is no centralized exception handling system in place for Swift runtime errors (out of bounds, nil unwrap, etc.); see this post. However, Xcode is still able to crash with EXC_BAD_INSTRUCTION, so my question stands: How is this possible, and why can't my signal handlers handle this?
ADDENDUM 2: Just to be safe, I tried registering my signal handler for all 20+ signals defined in signal.h (not just the ones listed above); still, no change.
ADDENDUM 3: Apple's official document Understanding and Analyzing Application Crash Reports contains this snippet:
Trace Trap [EXC_BREAKPOINT // SIGTRAP]
Similar to an Abnormal Exit, this exception is intended to give an
attached debugger the chance to interrupt the process at a specific
point in its execution. You can trigger this exception from your own
code using the __builtin_trap() function. If no debugger is attached,
the process is terminated and a crash report is generated.
Lower-level libraries (e.g, libdispatch) will trap the process upon
encountering a fatal error. Additional information about the error can
be found in the Additional Diagnostic Information section of the crash
report, or in the device's console.
Swift code will terminate with this exception type if an unexpected
condition is encountered at runtime such as:
a non-optional type with a nil value
a failed forced type conversion
Look at the Backtraces to determine where the unexpected condition was
encountered. Additional information may have also been logged to the
device's console. You should modify the code at the crashing location
to gracefully handle the runtime failure. For example, use Optional
Binding instead of force unwrapping an optional.
(emphasis mine)
Still: Why Can't I Handle This With My SIGTRAP Signal Handler?
TL;DR: Signal handler works fine when debugger is not attached.
(We can even catch fatal_error's SIGTRAP signal, and log stack-trace)
In order to see what was happening, I set up a small demo project where I registered a signal handler for SIGUSR1 (one of the 'user-defined' signals available) and subsequently sent said signal to my process using the kill() function:
kill(0, SIGUSR1);
At first, I wasn't able to have Xcode's debugger jump to my signal handler, and instead it would stop at the line with the kill() call, highlighting it in red just as in my question.
After reading this question and its answers, it struck me that the debugger must pretty much depend on signals in order to be able to stop/resume program execution e.g., at breakpoints.
Using the symbolic breakpoint specified in one of the answers:
process handle SIGUSR1 -n true -p true -s false
...I was able to make Xcode not stop on this command:
kill(pid, SIGUSR1);
...and instead jump to my signal handler, all while debugging. I could even step inside the signal handler and execute its statements one by one; display an alert view from within it, etc.
Although I am not able to achieve the same result with SIGTRAP (or even SIGABRT), my signal handler does get called (and my crash log does get saved to disk!) when I launch my app without a debugger attached (e.g., by tapping the app's icon on the home screen) and have it throw a Swift runtime error like the one I mentioned in my question.
My guess on why I was able to intercept unrecognized selector sent to instance... seems to be that, as an Objective-C exception, it is an entirely different beast from Unix signals, and has nothing to do with the workings of the debugger (unless you set up an exception breakpoint for "Objective-C exceptions"?).
The very fact that the handler is set with the unrelated function NSSetUncaughtExceptionHandler() should have been a hint...
(I'm pretty much talking out of my limited knowledge here, so please feel free to add answers/comments with corrections as you see fit)

EXC_BAD_ACCESS variable exists but doesn't?

I check for the variable's existence, but still get the exc_bad_access! How is this possible? I have tried Zombies, Instruments, and the console, to no avail, and about all else my limited knowledge can muster. Any other suggestions??
if (intDealerCard) {
NSLog(#"%i", intDealerCard); // EXC_BAD_ACCESS - code 2 occurs here
}
Perhaps some things of note...
The code is being executed over 1000 times, as it is a simulation, and it will execute just fine numerous times. I'd like to think there is a problem with my code, but the verified check throws me off. Also, there are two different spots where this may happen, mostly in one of the spots, but occasionally in the other, but still, I'm not sure that is relevant seeing how the check is verified?!
EXC_BAD_ACCESS occurs when memory hasn't been managed properly. Many times an app will crash with this error message in one place, however the memory management error has occurred elsewhere in the logic -- perhaps an unexpected dealloc is occurring on the instance of the class contains the member that is crashing, or if the app is running simulations concurrently, a race condition between a shared resource, etc. In short, the few lines of code in your question are likely not the culprit, just a symptom of a more systemic error with how that variable's memory is being managed.
As you've run Zombies and nothing has shaken loose, consider running the static analyzer (Product > Analyze) -- this class of error can sometimes be detected via static analysis and present one or more code flows that could resulting early release, unexpected deallocation, etc. These analysis errors and compiler warnings should be repaired and then you can retest using NSZombies if the error persists.

EXC_BAD_ACCESS with MKNetworkEngine

I'm using MKNetworkkit to parse XML data to the server. Before Entering into the success block its gets crash with EXC_BAD_ACCESS with out any reason and am already done with NSZombieEnabled like all the stuffs.![Below is the screen shot of where its getting crash.][1][1]: http://i.stack.imgur.com/FL3l9.png
You may find this useful to help debug http://subhb.org/2012/07/02/how-to-debug-exc_bad_access-error/
You will get EXC_BAD_ACCESS error mostly in the following scenarios:
You are trying to access an object that is not initialized.
You are trying to access an object that no longer exists. Either it’s being released or it’s nil. In ARC mode, make sure you take
ownership of the object that you want to use.
You are passing an message to an object that the object doesn’t understand. It can also happen for bad typecast.
Have you tried running breakpoints on your code and stepping through your program line by line and seeing if any of the above match the result?

Error vs. Exception in Dart

Why are there Errors AND Exceptions in Dart and not either Errors OR Exceptions?
Is the reason a historical one oder what?
I can throw an Error, I can throw an Exception. None of them is checked by the Analyzer like in Java (Exception vs. RuntimeException)
From this post, quoting Bob Nystrom:
Error and its subclasses are for programmatic errors. If one of those
occurs, your code is bad and you should fix your code.
Non-Error exception classes are for runtime errors. Sometimes you can
prevent them from being thrown, but often you cannot.
Except in a few special circumstances, idiomatic Dart should throw
Errors, but never catch them. They exists specifically to not be
caught so that they take down the app and alert the programmer to the
location of the bug.
In other words, you should expect (and check for) exceptions (it is intended that you should handle them). If you get an error, then you need to check how you're using the API that's throwing the error - you're probably using it wrong.
If you're writing an API, then you should use the same pattern. Errors are messages to downstream developers about how they are using your API.
Exception
An Exception in Dart should be thrown for regular, expected program flow and is intended to be caught:
An Exception is intended to convey information to the user about a failure, so that the error can be addressed programmatically. It is intended to be caught, and it should contain useful data fields.
Example: TimeoutException
A TimeoutException will be thrown "when a scheduled timeout happens while waiting for an async result", which is expected program flow.
If we have a download task for example and that download task is not finished after our specified timeout time of thirty seconds (which can happen), we want to communicate that to our user, hence, we need to catch the Exception.
Error
An Error in Dart should be thrown for unexpected program flow and should not be caught but addressed by the programmer:
An Error object represents a program failure that the programmer should have avoided.
Example: AssertionError
An AssertionError is thrown "when an assert statement fails", i.e. it should never happen because we assert that it should not.
If we see such an error, it means that we should change our code and we should definitely not catch the error.
In practice you can catch Errors, but you should not. There is a linter rule to help enforce that.
The fact that Dart allows it can still be useful, e.g. when testing assertions or other errors.
See this answer for a complete example scenario.
Exceptions are considered conditions that you can plan ahead for and catch.
Errors are conditions that you don't expect or plan for.
For more detailed ans
Thanks to Chris and from here
Exceptions should be used when there is a problem that is expected. A common one is any type of I/O operation (like network traffic), where the socket closes early, and trying to write data to that socket fails.
Errors occur when there is a problem that was not expected. Things like null pointers (you expected this variable to not be null), running our of memory, etc... When you try to use the API in a wrong way or stuffs like that.
For the most part you, as an app developer, will always use exceptions. Errors tend to be reserved for unexpected and fatal problems.

Resources