170 likes | 184 Views
This compilation provides an overview of exception handling in programming languages, including examples, traditional ways of handling exceptions, and the structured approach in C++, Ada, Java, and ML. It also covers the hierarchy and definition of exceptions, documenting exceptions, and exception propagation.
E N D
Exceptions (Section 8.5) CSCI 431 Programming Languages Fall 2003 A compilation of material developed by Felix Hernandez-Campos and Michael Scott
Exception Handling • Exception • unusual condition detected at run time • may require to "back-out" from several levels of subroutine calls • Examples: • arithmetic overflow • end-of-file on input • wrong type for input data • user-defined conditions (not necessarily errors), raised explicitly • "Traditional" ways to handle such situations: • return some default value when the real one cannot be obtained • return (or have an extra parameter) an explicit "status" value, to be inspected after each call • pass a closure for error handling, to be called in case of trouble
void f () { ... try { g(); } catch (exc) { // handle exception of type exc } ... } void g () { ... h(); ... } void h() { ... if (...) throw exc; ... } Exception Handling • Example (C++):
Exception Handling • Exception handler • code executed when exception occurs • different handler for each type of exception • Introduced by PL/I: ON condition statement • the statement is "remembered" for later use, if the condition (e.g. OVERFLOW) arises • if the condition arises: • execute statement • for "fatal" errors - terminate program • for "recoverable" errors – jump back to where exception occurred and continue execution
Exception Handling • C++, Ada, Java, ML – more structured approach: • handlers (catch in C++) are lexically bound to blocks of protected code (the code inside a try block in C++) • Exception propagation: • if an exception is raised (throw in C++): • if the exception is not handled in the current subroutine, return abruptly from subroutine • return abruptly from each subroutine in the dynamic chain of calls, until a handler is found • if found, execute the handler, then continue with code after handler • if no handler is found until outermost level (main program), terminate program
Exception Handling • Usage for exception handling mechanisms: • perform operations to recover, and then continue execution • allocate more memory • recover from errors in a compiler • cannot recover locally, but: • may want a local handler just to clean up some local resources • then re-raise the exception to be handled by a "higher authority" • terminate, but first print a helpful error message • Advantages: • uniform manner of handling errors • handle errors exactly where we want, without checking for them explicitly everywhere they might occur • subroutine documentation – specify what exceptions might be raised by a subroutine → subroutine user may want to catch them
Hierarchy of Exceptions • In PL/1, exception do not have a type • In Ada, all exceptions are of type exception • Exception handler can handle one specific exception or all of them • Since exceptions are classes in Java, exception handlers can capture an entire class of exceptions (parent classes and all its derived classes) • Hierarchy of exceptions
Definition of Exceptions • Exception types: • Predefined – dynamic semantic errors: • arithmetic overflow • division by zero • end-of-file on input • subscript and subrange out of bounds • null pointer dereference • User-defined: declare empty_queue : exception; -- Ada class empty_queue { }; // C ++
Definition of Exceptions • Parameterized exceptions – the code which raises the exception can pass additional information with it • C++: class duplicate_in_set { item dup; // element that was inserted twice } ... throw duplicate_in_set (d); • ML: exception duplicate_in_set of item; ... raise duplicate_in_set (d); • Ada, Common Lisp: • exceptions are just tags – no other information than the exception name
Definition of Exceptions • Documenting exceptions: • Modula-3 – mandatory to declare (in the subroutine header) all exceptions that may propagate out of the subroutine • if another exception propagates (not caught internally) → run-time error • C++ – optional list of exceptions • if the list is specified → same behavior as in Modula-3 • if the list is omitted → any exception can propagate • Java • “checked” exceptions – must be declared in subroutine headers • “unchecked” exceptions – may be omitted (e.g. fatal errors – array subscript out of bounds)
Exception Propagation • Exception handler – attached to a block of code (protected code) • Ada: with text_io; -- import I/O routines (and exceptions) procedure read_record (...) is begin ... begin ... -- protected code - potentially complex sequence of operations -- involving many calls to text_io.get ... exception when end_error => ... -- handler to catch any attempt to read past end_of_file -- in any of the I/O calls end; ... end read_record;
Exception Propagation • C++ (predefined exceptions): try { ... // protected block of code ... } catch (end_of_file) { ... } catch (io_error e) { // any io_error other than end_of_file ... } catch (...) { // all other exceptions; ... is part of syntax ... } • handler matches exception if it names a class from which exception is derived • can declare an exception object (e) – access additional information passed with the exception
Exception HandlersJava • Java uses lexically scoped exception handlers try { int a[] = new int[2]; a[4]; } catch (ArrayIndexOutOfBoundsException e) { System.out.println("exception: " + e.getMessage()); e.printStackTrace(); } • The dynamic chain is available using printStackTrace() • http://java.sun.com/products/jdk/1.2/docs/api/java/lang/Throwable.html
Implementation • Linked-list of dynamically-bound handlers maintained at run-time • Each subroutine has a default handler that takes care of the epilogue before propagating an exception • This is slow, since the list must be updated for each block of code • Compile-time table of blocks and handlers • Two fields: starting address of the block and address of the corresponding handler • Exception handling using a binary search indexed by the program counter • Logarithmic cost on the number of handlers
Java • Each subroutine has a separate exception handling table • Thanks to independent compilation of code fragments • Each stack frame contains a pointer to the appropriate table
C • Exception can be simulated • setjmp() can store a representation of the current program state in a buffer • Returns 0 if normal return, 1 if return from long jump • longjmp() can restore this state • Example: if (!setjmp(buffer)) { /* protected code */ } else { /* handler */ } • For more information: Longjmp
C • The state is usually the set of registers • longjmp() restores this set of registers • http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_20.html • Is this good enough? • Changes to variables before the long jump are committed, but changes to registers are ignored • If the handler needs to see changes to a variable that may be modified in the protected code, the programmer must include the volatile keyword in the variable’s declaration