NEW is called,
If a procedure cannot continue because of an exception, its caller might be able to handle it.
In general, exceptions are defined as the names of anomalous conditions:
ZERODIVIDE in PL/I and STORAGE_ERROR in Ada.
Raising (throwing in Java) an exception signals that an anomalous condition has occurred.
raise (throw) statements.
An exception handler is a segment of code that is designed to be activated when the corresponding exception is raised. Typically an exception handler is associated with a segment of code and is used to handle any exceptions that arise in execution of the code.
For example in Modula-3:
EXCEPTION BadFormat; ... TRY stmts EXCEPT BadFormat => handler-stmts END;Any exception occurring within
stmts immediately terminates
local execution and transfers control to handler-stmts.
Execution then proceeds normally following the TRY
statement.
Modula-3 also provides a clean-up style of handler that catches any exception whatsoever.
TRY stmts FINALLY cleanup-stmts END;Here,
cleanup-stmts will always be executed even if
an exception is raised in the execution of stmts.
However, if such an exception is raised, then it will be re-raised
after the execution of cleanup-stmts.
Modula-3 and other modern languages (e.g., CLU, Ada) statically
bind handlers to particular code segments.
In PL/I, the binding of handlers is dynamic; the current handler
in force for a given exception could be changed at any time
under the control of the programmer.
EXCEPTION BadFormat(Text);
...
TRY
stmts
EXCEPT
BadFormat(theString) =>
PutText("Enter a replacement for |"
theString "|.")
END;
This approach is somewhat more complex and less efficient,
but provides greater flexibility and readability.
- Using exception objects: (Java).
public class FileNotFoundException extends IOException {
public FileNotFoundException();
public FileNotFoundException(String s);
An elegant approach that also uses the subtype
hierarchy for catching exceptions.
Exceptions and Procedure Interfaces
In general, the idea of raising an exception is to signal a condition
that cannot be dealt with by the current procedure.
Thus the current procedure terminates abnormally and passes the
exception to its caller.
In Modula-3, CLU, and Java, the possibility that a procedure raises
an exception is considered part of its input-output specification
and must be explicitly declared in the procedure heading.
PROCEDURE ScanRealNumber
(str : Text) : REAL RAISES {BadFormat};
If a procedure terminates due to an exception, but that
procedure does not specify it in the header, then
- a special
failure exception is raised in CLU.
- a checked run-time error occurs in Modula-3.
In other languages the exception may be propagated back to
the caller of the procedure and the caller's caller and so on
until a handler is found. This is true in Modula-3 only
so long as each procedure header properly declares the exception.
Checking.
Compilers can check whether clients of procedures
- handle each possible exception, or
- declare the exception as a possible result
(automatic propagation)
Exception Handling versus Error Codes
In languages without exception handling mechanisms (e.g.,
C, Pascal), error flags are often used to signal the
occurrence of an anomaly.
These error flags may be either
- explicit return results of a subprogram, or
- global flags set by a subprogram.
In either case, the programmer is explicitly responsible for
checking for errors after the subprogram completes.
Exception handling mechanisms have two significant
advantages over the use of error codes.
- Safety.
What happens if an anomaly occurs in a subprogram, but the
programmer has not coded any error-handling procedures to
deal with it?
-
Using the error flags approach, execution simply
proceeds as if everything was OK.
In this case, the program will be in a corrupted
state which may eventually cause
- a system crash (bad),
- incorrect results to be computed (worse), or
- corruption of data files (worst).
- Using the exception handling approach, the lack
of a programmer-specified exception handler will cause
the program to terminate gracefully and report the
exception that was raised.
- Clarity of Algorithms.
In order to systematically handle all potential
anomalies in a program, the error flag approach requires
that tests be included after every call that might
report an anomaly. This can greatly obscure the
logic of an algorithm.
In the exception handling approach, handlers are
only coded at the point where it is actually possible
to handle an exception. None of the lower-level code
need be obscured with the details of error handling.