How does an error handler work internally? - c++

I know that there has to be quite a lot of documentation about this topic on the internet.
But doing research for hours without a proper answer is quite frustrating. So I assume I can't put my question in a good phrase. So here the full version:
I'm doing a presentation about try-catch, but it's rather boring to do the basic things. I know what try catch is and I know how it works.
But here comes the magic: Let's assume I use C++.
The compiler will create a read only list on the heap with structures that give information about the functions in the try-block. That includes pointers for start and end of the routine, information about about the object type of the exception and so on. (Please correct me if I'm wrong)
Okay. Now an exception occurs. The so called error handler (here we go, who is the error handler?) will look up all the data about the failing routine and get the appropriate catch routine. The correct catch is found by comparing the exception object that is generated through the error with the exception objects in the catch.
For example: InvalidCastException (or something like that) is created. There is a catch for that, the error is handled and all objects that are created in the try block are destroyed.
But: How can the program notice that there is an exception? Is this handled by the program, by the runtime or maybe even by the processor (I read something about Ring0 and Ring1, different levels in the CPU oO).

There are two ways of implementing exception handling in C++. First is to use Itanium ABI Zero-Cost exception handling. The second one is to use a pair of setjmp/longjmp to handle control flow for exceptions. The first is a preferred implementation for every modern compiler.
The program does not "listen" for exceptions, so it doesn't notice exceptions. Instead, it raises and processes them as part of the control flow. For example, "throw" is always raising an exception which triggers transfers the execution to exception handling code.
Even though these exceptions are heavily used in C++ which provides a nice interface to "throw" and "catch" them, they are also used in C, and even in the Linux kernel.
You can read more here:
http://sourcery.mentor.com/public/cxx-abi/abi-eh.html
http://llvm.org/docs/ExceptionHandling.html
Zero cost exception handling vs setjmp/longjmp

Related

When can the problem actually be fixed by catching an exception?

Here's the thing. There's something I don't quite understand about exceptions, and to me they seem like a construct that almost works, but can't be used cleanly.
I have a simple question. When has catching an exception been a useful or necessary component of solving the root cause of the problem? I.e. when have you been able to write code that fixes a problem signaled through an exception? I am looking for factual data, or experience you have had.
Here's what I mean. A normal program does work. If some piece of work can't be completed for reason X, the function responsible for doing the work throws an exception. But who catches the exception? As I see it, there are three reasons you might want to catch an exception:
You catch it because you want to change its type and rethrow it. (This happens when you translate mechanical exception, such as std::out_of_range, to business exceptions, such as could_not_complete_transaction)
You catch it because you want to log it, or let the user know about the problem, before aborting.
You catch it because you actually know how to solve the problem.
It is point 3 that I'm skeptical about. I have never actually caught an exception knowing what to do to solve it. When you get a std::out_of_memory, what are you supposed to do with it? It's not like you can barter the operating system to get more memory. That's just not something you can fix. And it's not just std::out_of_memory, there are also business class exceptions that suffer from this. Think about a potential connection_error exception: what can you do to fix this except wait and retry later and hope it fixes itself?
Now, to be fair, I do know of one case in which code does catch an exception and tries to fix the problem. I know that there are certain Win32 SEH handlers that catch a Stack Overflow exception and try to fix the problem by enlarging the size of the thread stack if it's possible. However, this works because SEH has try-resume semantics, which C++ exceptions don't have (you can't resume at the point the exception occurred).
The main part of the question is over. However, there's also another problem I have with exceptions that, to me, seems exactly the reason why you don't have catch clauses that fix the problem: the code that catches the exception necessarily has to be coupled with the code that throws it. Because, in order to fix the problem, it must have domain specific knowledge about what the problem cause is. But when some library documents that "if this function fails, an internal_error exception will be thrown", how am I supposed to be able to fix the problem when I don't know how the library works internally?
PS: Please note that this is not a "exceptions vs. error codes" kind of question; I am well aware that error codes suck as an error handling mechanism. They actually suffer from the same problem I have explained for exceptions.
I think your problem is that you equate "solve the problem" with "make the program keep going correctly". That is the wrong way to think of exceptions, or error handling in general.
Error handling code of any kind should not be something that is internally fixable by the program. That is, error handling logic (like catching exceptions) should not be entered because of programming mistakes.
If the user gives you a non-existent filename, that's not a programming mistake; that's a user-error. You cannot "fix" that without going back to the user and getting an existing file. But exceptions do allow you to undo what you were trying to do, restore the program to a valid state, and then communicate what happened to the user.
An invalid_connection is similarly not a programming mistake. Unlike the above, it's not necessarily a user error either. It's something that's expected to be able to happen, and different programs will handle it in different ways. Some will want to try again. Others will want to halt and let the user know.
The point is, because there is no one means to handle this condition, it cannot be done by the library. The error must be given to the caller of the library to figure out what to do.
If you have a function that parses integers, and you are given text that doesn't conform to an integer, it's not that function's job to figure out what to do next. The caller needs to be notified that the string they provided is malformed and that something ought to be done.
The caller needs to handle the error.
You don't abort most programs because a file that was supposed to contain integers didn't contain integers. But your parsing function does need to communicate this fact to the caller, and the caller does need to deal with that possibility.
That's what "catching exceptions" is for.
Now, unexpected environmental conditions like OOM are a different story. This is not usually external code's fault, but it's also not usually a programming error. And if it is a programming error (ie: memory leak), it's not one you can deal with in most cases. P0709 has an entire section on the ability (or lack thereof) of programs to be able to generally respond to OOM. The result is that, even when programs are coded defensively against OOM exceptions, they're usually still broken when they run out of memory.
Especially when dealing with OS's that don't commit pages to memory until you actually use them.
Here is my take,
There are more reasons to catch exceptions, for example, if it is a critical application, such as ones found in power substations etc. and an exception is caught to which there is no known system recovery or solution, you may want to have a controlled shutdown, protect certain modules, protect connected embedded systems etc. instead of just letting the system crash on its own. The latter could be disastrous...
I.e. when have you been able to write code that fixes a problem signaled through an exception?
When you get a std::out_of_memory, what are you supposed to do with it? It's not like you can barter the operating system to get more memory.
Actually I feel like that was my primary coding style for a while. An example: a system I worked on did not have a huge amount of memory and the system was dedicated, so, it was only my app and nothing else. Whenever I had an out_of_memory type of exception, I'd just kill the older process and open the one with the higher priority. Of course I'd wait for the kill to happen in a controlled fashion.
Think about a potential connection_error exception: what can you do to fix this except wait and retry later and hope it fixes itself?
I'd try to connect through another medium such as bluetooth, fiber, bus etc. Normally of course there would be a primary medium of contact, and the others wouldn't be called unless there is an exception.
But when some library documents that "if this function fails, an internal_error exception will be thrown", how am I supposed to be able to fix the problem when I don't know how the library works internally?
Most often an exception in a dedicated library has different consequences in your system than its own. You may not need to read the library and its internal workings to fix the problem. You just need to study its effect on your software and handle that situation. That's probably the easiest solution. And that is a lot easier to do if the library raises a known exception instead of just crashing or giving gibberish answers.
One obvious thing that came to mind was socket connections.
You try and connect to Server A and the program finds that it can't do that
Try connecting to Server B
The other examples regarding user input are equally as valid if not more so.
I admit that seeing something along the lines of
try
{
connectToServerA();
}
catch(cantConnectToServer)
{
connectToServerB();
}
would look like a bit of a weird pattern to see in real world code. It might make sense if the function takes an address and we iterate through a list of potential addresses.
Broadly speaking I agree with you often all you want to do is log the error and terminate - but some systems, which have to be robust and "always on" shouldn't just terminate if they encounter a problem.
Webservers are one obvious example. You don't just terminate because one users connection faulters, because that would drop the session for all the other connected users. There might be parts of code where raising an exception is the simplest way to deal with such a failure however.

How to wrap my C code in C++ exception handling?

I have an old C based project, which I would like to port from an Atmel processor to Raspberry Pi.
At the time that it was written, C++ was not an option, and it would be too much effort, almost a rewrite, to convert it all to C++.
Some problems/crashes can't be (easily) caught by C, so sometimes my program will just die & I would like to send a last chance cry for help before expiring. No attempt at recovery and I can even live without details of the error, just so long as I get a message telling me to visit the equipment
Long story short, I think that I could have better error detection if I had exception handling.
I am thinking of using exception handling as chance of alerting me to go to the device and fetch the complete error log, reset the hardware etc. C won't always give me that last gasp chance to do something, if my code goes bang
Since I don't want to do a total C++ rewrite, would it be enough just to wrap main() in try / catch?
Is that technically enough, or do I need to do more?
Other than more detailed error reporting, is there anything to gain by wrapping every (major) function in it's own try / catch?
Other than more detailed error reporting, is there anything to gain by wrapping every (major) function in it's own try / catch?
Firstly, only catch exceptions where you are in a position to alter the behaviour of the program in response to them (unless you're simply looking to add more contextual information via std::throw_with_nested())
Secondly, a c program will not exhibit RAII, so throwing exceptions in this circumstance is likely to leak resources unless you wrap all your handle and memory allocation in smart pointers or RAII-enabled handle classes.
You should do that before you consider adding exception handling.
If the program is likely to be actively maintained into the future, there is probably mileage in doing this. If not, probably better to leave sleeping dogs lie.

Should exceptions ever be caught

No doubt exceptions are usefull as they show programmer where he's using functions incorrectly or something bad happens with an environment but is there a real need to catch them?
Not caught exceptions are terminating the program but you can still see where the problem is. In well designed libraries every "unexpected" situation has actually workaround. For example using map::find instead of map::at, checking whether your int variable is smaller than vector::size prior to using index operator.
Why would anyone need to do it (excluding people using libraries that enforce it)? Basically if you are writing a handler to given exception you could as well write a code that prevents it from happening.
Not all exceptions are fatal. They may be unusual and, therefore, "exceptions," but a point higher in the call stack can be implemented to either retry or move on. In this way, exceptions are used to unwind the stack and a nested series of function or method calls to a point in the program which can actually handle the cause of the exception -- even if only to clean up some resources, log an error, and continue on as before.
You can't always write code that prevents an exception. Just for an obvious example, consider concurrent code. Let's assume I attempt to verify that i is between (say) 0 and 20, then use i to index into some array. So, I check and i == 12, so I proceed to use it to index into the array. Unfortunately, in between the test and the indexing operation, some other thread added 20 to i, so by the time it's used as an index, it's not in range any more.
The concurrency has led to a race condition, so the attempt at assuring against an exceptional condition has failed. While it's possible to prevent this by (for example) wrapping each such test/use sequence in a critical section (or similar), it's often impractical to do so--first, getting the code correct will often be quite difficult, and second even if you do get it correct, the consequences on execution speed may be unacceptable.
Exceptions also decouple code that detects an exceptional condition from code that reacts to that exceptional condition. This is why exception handling is so popular with library writers. The code in the library doesn't have a clue of the correct way to react to a particular exceptional condition. Just for a really trivial example, let's assume it can't read from a file. Should it print a message to stderr, pop up a MessageBox, or write to a log?
In reality, it should do none of these. At least two (and possibly all three) will be wrong for any given program. So, what it should do is throw an exception, and let code at a higher level determine the appropriate way to respond. For one program it may make sense to log the error and continue with other work, but for another the file may be sufficiently critical that its only reasonable reaction is to abort execution entirely.
Exceptions are very expensive, performance vise - thus, whenever performance matter you will want to write an exception free code (using "plain C" techniques for error propagation).
However, if performance is not of immediate concern, then exceptions would allow you to develop a less cluttered code, as error handling can be postponed (but then you will have to deal with non-local transfer of control, which may be confusing in itself).
I have used extensivelly exceptions as a method to transfer control on specific positions depending on event handling.
Exceptions may also be a method to transfer control to a "labeled" position alog the tree of calling functions.
When an exception happens the code may be thought as backtracking one level at a time and checking if that level has an exception active and executing it.
The real problem with exceptions is that you don't really know where these will happen.
The code that arrives to an exception, usually doesn't know why there is a problem, so a fast returning back to a known state is a good action.
Let's make an example: You are in Venice and you look at the map walking throught small roads, at a moment you arrive somewhere that you aren't able to find in the map.
Essentially you are confused and you don't understand where you are.
If you have the ariadne "μιτος" you may go back to a known point and restart to try to arrive where you want.
I think you should treat error handling only as a control structure allowing to go back at any level signaled (by the error handling routine and the error code).

Can I get a stack trace for un-handled (Objective) C++ exceptions?

I'm developing an iOS application that has recently grown a large C++ base. C++ is not my forte, and I'm getting frustrated by exceptions. What I'm looking for is a way to get a stack track to the site of an (un-handled) exception throw. I'll say that the "un-handled" qualifier is optional; I would settle for breaking on any exception throw as a last resort, though un-handled exceptions are ideal.
What I currently get is useless. Assuming I don't have any appropriate exception handlers higher up the callstack, and I do something like
std::vector<int> my_vector;
my_vector.at(40) = 2; // Throws std::out_of_range
The app will break in main() and I'll get a log message saying "terminate called throwing an exception." Not helpful.
Putting generic try/catch blocks higher up the callstack doesn't help either, because the callstack is unwound during exception handling up to the point of the catch block, leaving me ignorant to actual origin of the exception. This also applies to providing my own terminate_handler. Asserts are more useful, but they require me to anticipate error conditions to some extent, which I cannot always do. I would still like the debugger to be able to step in even if an unexpected exception makes it past my pre-emptive assert()s.
What I want to avoid is having to wrap every call that might possibly throw an exception in a try/catch block just to get the stack trace to the error. At runtime, I'm really not interested in catching these exceptions. When they occur, it means there's a fatal flaw in the program execution, and there's no way it can continue normally. I just want to be notified so I can determine the cause and mend the issue so it won't happen again.
In Objective C, I can put a symbolic breakpoint on objc_exception_throw, and any time I screw something up I'll immediately break execution and be presented with a nice stack trace so I know where the issue is. Very helpful.
I realize this behavior is really only useful because of a philosophical difference in exception handling between the two languages. Objective C exceptions are intended only to signify unrecoverable errors. The task of routine error handling is accomplished via error return codes. This means that any Objective C exception is a great candidate for a breakpoint to the developer.
C++ seems to have a different use for Exceptions. They're used to handle both fatal errors and routine errors (at least in the 3rd party libs I'm using). This means I might not actually want to break on every exception that's thrown in C++, but I would still find the ability useful if I can't break only on un-handled exceptions.
You can quickly establish a break on all C++ throw conditions in Xcode:
cmd+6
"+" button -> Add Exception Breakpoint
C++ -> std::out_of_range
On Throw
Update
If you have a lot of them tho filter out, you may prefer to:
Create a Symbolic Breakpoint
Symbol = __cxa_throw (may vary by std library)
Action > Debugger Command = bt
Automatically continue after eval = On
The bt command logs the backtrace. Configured this way, it will automatically continue.
So, this will just log the backtrace of every thrown exception - when your program terminates due to an unhandled exception, the clues will be among the final logged backtraces (often the last, unless the library rethrows).
In the app I get to debug with many c++ exceptions, I leave the "Catch C++ Exceptions on Throw" off until I get to the point in the app where it will throw the exception, then I turn that option on and usually the next exception that is thrown is what I'm looking for. This will break a few levels deeper than where the error is, but the stack is intact so you can figure out what is going on.
Check PLCrashReporter. We use it with our application (which relies heavily on C++) and it produces stack traces even for the C++ code.
The only problem you might have is when using assembly routines which were not written natively for iOS (Apple's compiler is using R7 to hold the stack frame for tracing back symbols which is not according to official ARM EBI)

Getting a stack trace in C++ exceptions

The fact a stack/function trace is supplied in Java/C# exceptions is really useful. Is there a handy way to do this in C++ or would I have to bake extra data into every method/function?
Most debuggers can be set up to pause your program each time an exception is thrown (either any exception or an exception for which there's no handler) so that you can obserevr a call stack.
Also if your code only throws exceptions of classes you control you can put code for dumping the call stack in those classes constructors.
If you are considering adding metdata to your exceptions, You may consider using boost exception handling . boost::exception allows adding information to an exception after it has been thrown.
Some OS APIs provide for stack traces, I know that the Windows API has StackWalk64 or something like that that can do stack tracing.
However, if you can't depend on such a thing, then pretty much all you can do is either ship a debug build, or do it manually.