Computer Programming/Error Handling
Computer Programming/Error Handling
2 Language overview
if C < 0 then
error handling
else
normal processing
fi
Our example make use of the fact that all valid return values for √ are positive and
therefore -1 can be used as an error indicator. However this technique won't work when
all possible return values are valid and no return value is available as error indicator.
function √ (
X : in Float;
Success : out Boolean ) : Float
begin
if (X < 0) :
Success := False
else
calculate root from x
Success := True
fi
end
C := √ (A2 + B2, Success)
An error condition is stored inside a global variable. This variable is then read directly or
indirectly via a function.
if Float_Error then
error handling
else
normal processing
fi
As you can see from the source the problematic part of this technique is choosing the
place at which the flag is reset. You could either have the callee or the caller do that.
[edit] Exceptions
The programming language supports some form of error handling. This ranges from the
classic ON ERROR GOTO ... from early Basic dialects to the try ... catch exceptions
handling from modern object oriented languages.
The idea is always the same: you register some part of your program as error handler to
be called whenever an error happens. Modern designs allow you to define more than one
handler to handle different types of errors separately.
Once an error occurs the execution jumps to the error handler and continues there.
The great strength of exceptions handling is that it can block several operations within
one exception handler. This eases up the burden of error handling since not every
function or procedure call needs to be checked independently for successful execution.
In Design by Contract (DbC) functions must be called with the correct parameters. This
is the caller's part of the contract. If the types of actual arguments match the types of
formal arguments, and if the actual arguments have values that make the function's
preconditions True, then the subprogram gets a chance to fulfill its postcondition.
Otherwise an error condition occurs. Now you might wonder how that is going to work.
Let's look at the example first:
function √ (X : in Float) : Float
pre-condition (X >= 0)
post-condition (return >= 0)
begin
calculate root from x
end
C := √ (A2 + B2)
As you see the function demands a precondition of X >= 0 - that is the function can only
be called when X ≥ 0. In return the function promises as postcondition that the return
value is also ≥ 0.
In a full DbC approach, the postcondition will state a relation that fully describes the
value that results when running the function, something like result ≥ 0 and X =
result * result. This postcondition is √'s part of the contract. The use of assertions,
annotations, or a language's type system for expressing the precondition X >= 0 exhibits
two important aspects of Design by Contract:
1. There can be ways for the compiler, or analysis tool, to help check the contracts.
(Here for example, this is the case when X ≥ 0 follows from X's type, and √'s
argument when called is of the same type, hence also ≥ 0.)
2. The precondition can be mechanically checked before the function is called.
The 1st aspect adds to safety: No programmer is perfect. Each part of the contract that
needs to be checked by the programmers themselves has a high probability for mistakes.
The 2nd aspect is important for optimization — when the contract can be checked at
compile time, no runtime check is needed. You might not have noticed but if you think
about it: A2 + B2 is never negative, provided the exponentiation operator and the addition
operator work in the usual way.
We have made 5 nice error handling examples for a piece of code which never fails. And
this is the great opportunity for controlling some runtime aspects of DbC: You can now
safely turn checks off, and the code optimizer can omit the actual range checks.
DbC languages distinguish themselves on how they act in the face of a contract breach:
1
: Ada supports a very limited form of DbC through its strong typing system.
2
: In C and C++ the behavior is defined and sometimes intentionally used however in this comparison we
consider unintentional use.
Handler Examples
If any error condition arises (other than a NOT FOUND), continue execution after
setting l_error=1: