Applications of explicitly raising exceptions - exception

What are the applications and advantages of explicitly raising exceptions in a program. For example, if we consider Ada language specifically here provides an interface to raise exceptions in the program. Example:
raise <Exception>;
But what are the advantages and application areas where we would need to raise exceptions explicitly?
For example, in a procedure which accepts one of the parameters as string:
function Fixed_Str_To_Chr_Ptr (Source_String : String) return C.Strings.Chars_Ptr is
...
begin
...
-- Check whether source string is of acceptable length
if Source_String'Length <= 100 then
...
else
...
raise Constraint_Error;
end if;
return Ptr;
exception
when Constraint_Error=>
.. Do Something..
end Fixed_Str_To_Chr_Ptr;
Is there any advantage or good practice if I raise an exception in the above function and handle it when the passed string length bound exceeds the tolerable limits? Or a simple If-else handler logic should do the business?

I'll make my 2 cents an answer in order to bundle the various aspects. Let's start with the general question
But what are the advantages and application areas where we would need to raise exceptions explicitly?
There are a few typical reasons for raising exceptions. Most of them are not Ada-specific.
First of all there may be a general design decision to use or not use exceptions. Some general criteria:
Exception handlers may incur a run time cost even if an exception is actually never thrown (cf. e.g. https://gcc.gnu.org/onlinedocs/gnat_ugn/Exception-Handling-Control.html). That may be unacceptable.
Issues of inter-operability with other languages may preclude the use of exceptions, or at least require that none leave the part programmed in Ada.
To a degree the decision is also a matter of taste. A programmer coming from a language without exceptions may feel more confident with a design which just relies on checking return values.
Some programs will benefit from exceptions more than others. If traditional error handling obscures the actual program structure it may be time for exceptions. If, on the other hand, potential errors are few, easily detected and can be handled locally, exceptions may obscure potential execution paths more than handling errors traditionally would.
Once the general decision to use exceptions has been made the problem arises when and when not it is appropriate to raise them in your code. I mentioned one general criteria in my comment. What comes to mind:
Exceptions should not be part of normal, expected program flow (they are called exceptions, not expectations ;-) ). This is partly because the control flow is harder to see and partly because of the potential run time cost.
Errors which can be handled locally don't need exceptions. (It can still be useful to raise one in order to have a uniform error handling though. I'll discuss that below when I get to your code snippet.)
On the other hand, exceptions are great if a function has no idea how to handle errors. This is particularly true for utility and library functions which can be called from a variety of contexts (GUI, console program, embedded, server ...). Exceptions allow the error to propagate up the call chain until somebody can handle it, without any error handling code in the intervening layers.
Some people say that a library should only expose custom exceptions, at least for any anticipated errors. E.g. when an I/O exception occurs, wrap it in a custom exception and explicitly raise that custom exception instead.
Now to your specific code question:
Is there any advantage or good practice if I raise an exception in the above function and handle it when the passed string length bound exceeds the tolerable limits? Or a simple If-else handler logic should do the business?
I don't particularly like that (although I don't find it terrible) because my general argument above ("if you can handle it locally, don't raise") would indicate that a simple if/else is clearer.1 For example, if the function is long the exception handler will be far away from the error location, so one may wonder where exactly the exception could occur (and finding one raise location is no guarantee that one has found them all, so the reviewer must scrutinize the whole function!).
It depends a bit on the specific circumstances though. Raising an exception may be elegant if an error can happen in several places. For example, if several strings can be too short it may be nice to have a centralized error handling through the exception handler, instead of scattering if/then/elses (nested??) across the function body. The situation is so common that a legitimate case can be made for using goto constructs in languages without exceptions. An exception is then clearly superior.
1But in all reality, how do you handle that error there? Do you have a guaranteed logging facility? What do you return? Does the caller know the result can be invalid? Maybe you should throw and not catch.

There are two problems with the given example:
It's simple enough that control flow doesn't need the exception. That won't always be the case, however, and I'll come back to that in a moment.
Constraint_Error is a spectacularly bad exception to raise, to detect a string length error. The standard exceptions Program_Error, Constraint_Error, Storage_Error ought to be reserved for programming error conditions, and in most circumstances ought to bring down the executable before it can do any damage, with enough debugging information (a stack traceback at the very least) to let you find the mistake and guarantee it never happens again.
It's remarkably satisfying to get a Constraint_Error pointing spookily close to your mistake, instead of whatever undefined behaviour happens much later on... (It's useful to learn how to turn on stack tracebacks, which aren't generally on by default).
Instead, you probably want to define your own String_Size_Error exception, raise that and handle it. Then, anything else in your unshown code that raises Constraint_Error will be properly debugged instead of silently generating a faulty Chars_Ptr.
For a valid use case for raising exceptions, consider a circuit simulator such as SPICE (or a CFD simulator for gas flow, etc). These tools, even when working properly, are prone to failures thanks to numerical problems that happen in matrix computations. (Two terms cancel, producing zero +/- rounding error, which causes infeasibly large numbers or divide-by-zero later on). It's often an iterative approximation, where the error should reduce in each step until it's an acceptably low value. But if a failure occurs, the error term will start growing...
Typically the simulation happens step by step, where each step is a sufficiently small time step, maybe 1 us or 1 ns. The main loop requests a step, and this request is passed to thousands of agents in the simulation representing components in a circuit, or triangles in a CFD mesh.
Any one of those agents may fail to compute a solution, and the cleanest way to handle a failure is to raise an exception, maybe Convergence_Error. There may be thousands of possible points where an exception can be raised.
Testing thousands of return codes would get ugly fast. But with exceptions, the main loop only needs one handler, which takes some corrective action such as reducing the simulation step size and running the step again.
Sanitizing user text input in a browser may be another good use case, closer to the example code.
One word on the runtime cost of exceptions : the Gnat compiler and its RTS supports a "Zero Cost Exception" (ZCX) model - at least for some targets. There's a larger penalty when an exception is raised, as a tradeoff against eliminating the penalty in the normal case. If the penalty matters to you, refer to the documentation to see if it's worthwhile 9or even possible) in your case.

You raise an exception explicitly to control which exception is reported to the user of a subprogram. - Or in some cases just to control the message associated with the raised exception.
In very special cases you may also raise an exception as a program flow control.

Exceptions should stay true to their name, which is to represent exceptional situations.

Related

Ada Exceptions in Safety Critical Embedded Systems [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I started learning Ada for its potential use in an embedded device which is safety critical. So far, I'm really liking it. However, in my research on embedded programming, I came across the hot topic of whether to use exception handling in embedded systems. I think I understand why some people seem to avoid it:
depending on its implementation it can introduce either run-time overhead or larger code size (mentioned here under "Implementation")
the time it takes to execute exceptions can be non-deterministic (one of several sources I saw)
Now my question is, Does the Ada language or the GNAT compiler address these concerns? My understanding of safety critical code is that non-deterministic code size and execution time is often not acceptable.
Due Diligence: I am having a bit of trouble finding out exactly how deterministic Ada exceptions can be, but my understanding is their original implementation called for more run-time overhead in exchange for reduced code size impact (above first link mentions Ada explicitly). Beyond the above first link, I have looked into profiles mentioning determinism of code, like the Ravenscar profile and this paper, but nothing seems to mention exception handling determinism. To be fair, I may be looking in the wrong places, as this topic seems quite deep.
There are embedded systems that are safety- or mission-critical, embedded systems that are hard real time, and embedded systems that are both.
Embedded systems that are hard real time may be constrained or not. Colleagues worked on a missile guidance system in the 70s that had about 4 instructions worth of headroom in its main loop! (as you can imagine, it was written in assembler and used a tuned executive, not an RTOS. Exceptions weren't supported). On the other hand, the last one I worked on, on a 1 GHz PowerPC board, had a 2 millisecond deadline for the response to a particular interrupt, and our measured worst case was 1.3 milliseconds (and it was a soft real time requirement anyway, you just didn't have to miss too many in a row).
That system also had safety requirements (I know, I know, safe missile systems, huh) and although we were permitted to use exceptions, an unhandled exception meant that the system had to be shut down, missile in flight or no, resulting in loss of missile. And we were strictly forbidden to say when others => null; to swallow an exception, so any exception we didn't handle would be 'unhandled' and would bounce up to the top level.
The argument is, if an unhandled exception happens, you can no longer know the state of the system, so you can't justify continuing. Of course, the wider safety engineering has to consider what action the overall system should take (for example, perhaps this processor should restart in a recovery mode).
Sometimes people use exceptions as part of their control flow; indeed, for handling random text inputs a commonly used method is, rather than checking for end of file, just carry on until you get an End_Error;
loop
begin
-- read input
-- process input
exception
when End_Error => exit;
end;
end loop;
Jacob's answer discusses using SPARK. You don't have to use SPARK to not handle exceptions, though of course it would be nice to be able to prove to yourself (and your safety auditor!) that there won't be any. Handling exceptions is very tricky, and some RTSs (e.g Cortex GNAT RTS) don't; the configuration pragma
pragma Restrictions (No_Exception_Propagation);
means that exceptions can't be propagated out of the scope where they're raised (the program will crash out with a call to a Last_Chance_Handler).
Propagating exceptions only withon the scope where they're raised isn't, IMO, that useful:
begin
-- do something
if some error condition then
raise Err;
end if;
-- do more
exception
when Err =>
null;
end;
would be a rather confusing way of avoiding the "do more" code. Better to use a label!
Exceptions are deterministic in Ada. (But some checks which can raise an exception have some freedom. If the compiler can provide a correct answer, it doesn't always have to raise an exception, if an intermediate result is out of bounds for the type in question.)
At least one Ada compiler (GNAT) has a "zero cost" exception implementation. This doesn't make exceptions completely free, but you don't pay a run-time cost until you actually raise an exception. You still pay a cost in terms of code space. How large that cost is depends on the architecture.
I haven't worked on safety critical systems myself, but I know for sure that the run-time used for the software in the Ariane 4 inertial navigation system included exceptions.
If you don't want exceptions, one option is to use SPARK (a language derived from Ada). You can still use any Ada compiler you like, but you use the SPARK tools to prove that the program can't raise any exceptions. You should note that SPARK isn't magic. You have to help the tools, by inserting assertions, which the tools can use as intermediate steps for the proofs.

To use mem and then find or to use find and handle the exception?

Suppose, I want to write a function that tries to find a key in a map and returns None if it cannot: try_find: 'a -> ('a, 'b) Map.t -> 'b option, what is the canonical way to do this? To first check that the key exists with mem and then call find? Or to catch the Not_found exception? Batteries seem to do the latter.
On the other hand, in languages like C# or Java people are usually discouraged from using exceptions in such cases, for performance reasons. Is using exceptions on "normal" execution paths a usual thing in Ocaml or is it also discouraged?
OCaml exceptions are as fast as function calls for the default backend. For Javascript backends, it is not always true. The canonical OCaml way is to implement a function that doesn't throw an exception is to use a throwing function and translate the exception to a nullary variant, e.g.,
let try_find x xs = try Some (List.find x xs) with Not_found -> None
Calling mem and find is a loss of performance, as you will actually iterate the list twice.
There are tradeoffs between raising an exception and returning an option type. The standard function List.find will not allocate any new values in the heap, so no garbage will be created. On the other hand, the try_find function will allocate a new value every time something is found (None is a constant so it is not allocated). This will create an extra work for the garbage collector, that will eventually degrade the performance. To me, the semantic benefits of total functions outweigh possible performance degradation. If the latter does matter (in case of tight loops) then I can always optimize it locally by either using an exception in a very tight context, or continuation passing style and/or GADT.
Is using exceptions on "normal" execution paths a usual thing in Ocaml or is it also discouraged?
It wasn't discouraged by the design of the language, and OCaml standard library uses exceptions a lot. However, the language evolves, and new features are added to the language. Moreover, new backends are implemented, like several Javascript backends, Java, and .Net backends. It is not trivial, to provide the same performance guarantees for these backends. So with a time, the popularity of exceptions reduced, and many people started to favor total functions with explicitly encoded errors, cf., the newly added to the standard library result type. Another example is Janestreet Core library (and all other libraries) that disfavor exceptions and use them only for exceptional cases.
You should decide by yourself an exception policy (or borrow the existing one). My personal policy is trying to avoid them in the public interfaces and sparingly use them very locally. I also use exceptions, for logic and programmer errors, basically, for errors, that shouldn't be captured.
From what I've seen, OCaml exceptions are quite efficient, and I see them being used more often than in other functional languages I guess.
I try to avoid them myself as they interfere with reasoning about the program. But a self-contained use in a library doesn't seem so bad.
The efficiency of low-level things like exceptions is something that might vary a lot from platform to platform. I suspect that catching the Not_found exception would be faster for very large maps, as it avoids traversing the map twice. Otherwise it might not matter much.

OS development: How to avoid an infinite loop after an exception routine

For some months I've been working on a "home-made" operating system.
Currently, it boots and goes into 32-bit protected mode.
I've loaded the interrupt table, but haven't set up the pagination (yet).
Now while writing my exception routines I've noticed that when an instruction throws an exception, the exception routine is executed, but then the CPU jumps back to the instruction which threw the exception! This does not apply to every exception (for example, a div by zero exception will jump back to the instruction AFTER the division instruction), but let's consider the following general protection exception:
MOV EAX, 0x8
MOV CS, EAX
My routine is simple: it calls a function that displays a red error message.
The result: MOV CS, EAX fails -> My error message is displayed -> CPU jumps back to MOV CS -> infinite loop spamming the error message.
I've talked about this issue with a teacher in operating systems and unix security.
He told me he knows Linux has a way around it, but he doesn't know which one.
The naive solution would be to parse the throwing instruction from within the routine, in order to get the length of that instruction.
That solution is pretty complex, and I feel a bit uncomfortable adding a call to a relatively heavy function in every affected exception routine...
Therefore, I was wondering if the is another way around the problem. Maybe there's a "magic" register that contains a bit that can change this behaviour?
--
Thank you very much in advance for any suggestion/information.
--
EDIT: It seems many people wonder why I want to skip over the problematic instruction and resume normal execution.
I have two reasons for this:
First of all, killing a process would be a possible solution, but not a clean one. That's not how it's done in Linux, for example, where (AFAIK) the kernel sends a signal (I think SIGSEGV) but does not immediately break execution. It makes sense, since the application can block or ignore the signal and resume its own execution. It's a very elegant way to tell the application it did something wrong IMO.
Another reason: what if the kernel itself performs an illegal operation? Could be due to a bug, but could also be due to a kernel extension. As I've stated in a comment: what should I do in that case? Shall I just kill the kernel and display a nice blue screen with a smiley?
That's why I would like to be able to jump over the instruction. "Guessing" the instruction size is obviously not an option, and parsing the instruction seems fairly complex (not that I mind implementing such a routine, but I need to be sure there is no better way).
Different exceptions have different causes. Some exceptions are normal, and the exception only tells the kernel what it needs to do before allowing the software to continue running. Examples of this include a page fault telling the kernel it needs to load data from swap space, an undefined instruction exception telling the kernel it needs to emulate an instruction that the CPU doesn't support, or a debug/breakpoint exception telling the kernel it needs to notify a debugger. For these it's normal for the kernel to fix things up and silently continue.
Some exceptions indicate abnormal conditions (e.g. that the software crashed). The only sane way of handling these types of exceptions is to stop running the software. You may save information (e.g. core dump) or display information (e.g. "blue screen of death") to help with debugging, but in the end the software stops (either the process is terminated, or the kernel goes into a "do nothing until user resets computer" state).
Ignoring abnormal conditions just makes it harder for people to figure out what went wrong. For example, imagine instructions to go to the toilet:
enter bathroom
remove pants
sit
start generating output
Now imagine that step 2 fails because you're wearing shorts (a "can't find pants" exception). Do you want to stop at that point (with a nice easy to understand error message or something), or ignore that step and attempt to figure out what went wrong later on, after all the useful diagnostic information has gone?
If I understand correctly, you want to skip the instruction that caused the exception (e.g. mov cs, eax) and continue executing the program at the next instruction.
Why would you want to do this? Normally, shouldn't the rest of the program depend on the effects of that instruction being successfully executed?
Generally speaking, there are three approaches to exception handling:
Treat the exception as an unrepairable condition and kill the process. For example, division by zero is usually handled this way.
Repair the environment and then execute the instruction again. For example, page faults are sometimes handled this way.
Emulate the instruction using software and skip over it in the instruction stream. For example, complicated arithmetic instructions are sometimes handled this way.
What you're seeing is the characteristic of the General Protection Exception. The Intel System Programming Guide clearly states that (6.15 Exception and Interrupt Reference / Interrupt 13 - General Protection Exception (#GP)) :
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the instruction that generated the
exception.
Therefore, you need to write an exception handler that will skip over that instruction (which would be kind of weird), or just simply kill the offending process with "General Protection Exception at $SAVED_EIP" or a similar message.
I can imagine a few situations in which one would want to respond to a GPF by parsing the failed instruction, emulating its operation, and then returning to the instruction after. The normal pattern would be to set things up so that the instruction, if retried, would succeed, but one might e.g. have some code that expects to access some hardware at addresses 0x000A0000-0x000AFFFF and wish to run it on a machine that lacks such hardware. In such a situation, one might not want to ever bank in "real" memory in that space, since every single access must be trapped and dealt with separately. I'm not sure whether there's any way to handle that without having to decode whatever instruction was trying to access that memory, although I do know that some virtual-PC programs seem to manage it pretty well.
Otherwise, I would suggest that you should have for each thread a jump vector which should be used when the system encounters a GPF. Normally that vector should point to a thread-exit routine, but code which was about to do something "suspicious" with pointers could set it to an error handler that was suitable for that code (the code should unset the vector when laving the region where the error handler would have been appropriate).
I can imagine situations where one might want to emulate an instruction without executing it, and cases where one might want to transfer control to an error-handler routine, but I can't imagine any where one would want to simply skip over an instruction that would have caused a GPF.

Real time system exception handling

As always after some research I was unable to find anything of real value. My question is how does one go about handling exceptions in a real time system? As program failure generally is not the best case i.e. nuclear reactor/ heart monitor.
Ok since everyone got lost on the second piece of this, which had NOTHING to do with the main question. I had it in there to show how I normally escape code blocks.
Exception handling in real-time/embedded systems has several layers. Not just the language supported options, but also MMU, CPU exceptions and one of my favorites: watchdogs.
Language exceptions (C/C++)
- not often used, beause it is hard to prove that all exceptions are handled at the right level. Also it is pretty hard to determine what threat/process should be responsible. Instead, programming by contract is preferred.
Programming style:
- i.e. programming by contract. Additional constraints : Misra/C Misra/C++. This can be checked to unsure that all possible cases are somehow handled. (i.e. no if without else)
Hardware support:
- MMU : use of multiple processes which are protected against each other. This allows
- watchdog
- CPU exceptions
- multi core: use of multiple cores to separate cricical processes from the rest. Also allows to have voting mechanisms (you want this and more for your nuclear reactor).
- multi-system
Most important is to define a strategy. Depending on the other nonfunctional requirements (safety, reliability, security) a strategy needs to be thought of. Can be graceful degradation to partial system reboot.
In a 'real-time', 'nuclear reactor' type system, chances are the exception handling allows the system to instead of fail, do the next best thing.
Let's say that we have a heart monitor. If it isn't receiving a signal, that might trigger an exception. In that case, the heart monitor might handle the exception by waiting a few seconds and trying again.
In a nuclear reactor, getting to a certain temperature might trigger an exception. In that case, the handling might shut off various parts of the reactor to start to cool it down, and then start them back up when it gets to a reasonable temperature.
Exceptions are meant to have a lower-level system say that it doesn't know what to do, and to have a higher level system handle it. Like in the nuclear reactor, the system that measures temperature probably doesn't know how to turn on parts of the reactor, so it triggers an exception so that some higher-level system can handle it.
A critical system is like any other system, except it's specified more clearly, passes through more testing phases, and is generally will fail-safe.
Regarding your form, yes it's pretty bad. I do mind the lack of {} very much; and it's been said so-often that this is just plain bad style, and leads to confusion when adding new code.

Try Catch blocks inside or outside of functions and error handing

This is more a general purpose programming question than language specific. I've seen several appraoches to try and catches.
One is you do whatever preprocessing on data you need, call a function with the appropriate arguments and wrap it into a try/catch block.
The other is to simply call a function pass the data and rely on try catches within the function, with the function returning a true/false flag if errors occured.
Third is a combination with a try catch outside the function and inside. However if the functions try catch catches something, it throws out another exception for the try catch block outside the function to catch.
Any thoughts on the pros/cons of these methods for error control or if there is an accepted standard? My googling ninja skills have failed me on finding accurate data on this.
In general, an exception should only be caught if it can actually be handled.
It makes no sense to catch an exception for no purpose other than to log it. The exception is that exceptions should be caught at the "top level" so that it can be logged. All other code should allow exceptions to propagate to the code that will log them.
I think the best way to think about this is in terms of program state. You don't want a failed operation to damage program state. This paper describes the concept of "Exception Safety".
In general, you first need to decide what level of exception safety a function needs to guarantee. The levels are
Basic Guarnantee
Strong Guarantee
NoThrow Guarantee
The basic Guarantee simply means that in the face of an exception or other error, no resources are leaked, the strong guarantee says that the program state is rolled back to before the exception, and nothrow methods never throw exceptions.
I personally use exceptions when an unexpected, runtime failure occurs. Unexpected means to me that such a failure should not occur in the normal course of operations. Runtime means that the error is due to the state of some external component outside of my control, as opposed to due to logic errors on my part. I use ASSERT()'s to catch logic errors, and I use boolean return values for expected errors.
Why? ASSERT isn't compiled into release code, so I don't burden my users with error checking for my own failures. That's what unit tests and ASSERTS are for. Booleans because throwing an exception can give the wrong message. Exceptions can be expensive, too. If I throw exceptions in the normal course of application execution, then I can't use the MS Visual Studio debugger's excellent "Catch on thrown" exception feature, where I can have the debugger break a program at the point that any exception is thrown, rather than the default of only stopping at unhandled (crashing) exceptions.
To see a C++ technique for the basic Guarantee, google "RAII" (Resource Acquisition is Initialiation). It's a technique where you wrap a resource in an object whose constructor allocates the resource and whos destructor frees the resource. Since C++ exceptions unwind the stack, it guarantees that resources are freed in the face of exceptions. You can use this technique to roll back program state in the face of an exception. Just add a "Commit" method to an object, and if an object isn't committed before it is destroyed, run the "Rollback" operation that restores program state in the destructor.
Every "module" in an application is responsible for handling its own input parameters. Normally, you should find issues as soon as possible and not hand garbage to another part of the application and rely on them to be correct. There are exceptions though. Sometimes validating an input parameter basically needs reimplementing what the callee is supposed to do (e.g. parsing an integer) in the caller. In this case, it's usually appropriate to try the operation and see if it works or not. Moreover, there are some operations that you can't predict their success without doing them. For example, you can't reliably check if you can write to a file before writing to it: another process might immediately lock the file after your check.
There are no real hard and fast rules around exception handling that I have encountered, however I have a number of general rules of thumb that I like to apply.
Even if some exceptions are handled at the lower layer of your system make sure there is a catch all exception handler at the entry point of your system (e.g. When you implement a new Thread (i.e. Runnable), Servlet, MessasgeDrivenBean, server socket etc). This is often the best place to make the final decision as how your system should continue (log and retry, exit with error, roll back transaction)
Never throw an execption within a finally block, you will lose the original exception and mask the real problem with an unimportant error.
Apart from that it depends on the function that you are implementing. Are you in a loop, should the rest of the items be retried or the whole list aborted?
If you rethrow an exception avoid logging as it will just add noise to your logs.
I generally consider if as the caller of the method I can use an exception in any way (like, to recover from it by taking a different approach) or if it makes no difference and just went wrong if the exception occurs. So in the former case I'll declare the method to throw the exception while in the latter I'll catch it inside of the method and don't bother the caller with it.
The only question on catching exceptions is "are there multiple strategies for getting something done?"
Some functions can meaningfully catch certain exceptions and try alternative strategies in the event of those known exceptions.
All other exceptions will be thrown.
If there are not any alternative strategies, the exception will be simply thrown.
Rarely do you want a function to catch (and silence) exceptions. An exception means that something is wrong. The application -- as a whole -- should be aware of unhandled exceptions. It should at least log them, and perhaps do even more: shut down or perhaps restart.