160 likes | 170 Views
Explore exception design, binding, continuation, and user-defined exceptions in PL/I, Ada, C++, and Java. Learn about built-in exceptions and handling mechanisms. Discover the dynamic nature of exception handling in different languages.
E N D
Exception handling (EH) allows a programmer to provide code in the program to handle run-time errors or exceptional situations this improves reliability EH was first introduced in PL/I and found in few languages (except for EOF-types of mechanisms) until C++ EH has been included in most modern languages since C++ since their utility greatly improves reliability Here, we look at PL/I, Ada, C++ and Java and briefly consider Events as a special form of exception design issues: how/where are exception handlers specified and what is their scope? how is an exception bound to a handler? where does execution continue after the handler executes (continuation) how are user-defined exceptions specified, if at all? are there predefined exceptions? If so, should there be default handlers for them? can predefined exceptions be explicitly raised? are hardware errors treated as exceptions to be handled? should it be possible to disable predefined exceptions? Exception Handling
Binding and Continuation Exception handler binding determines which handler can handle the exception Continuation determines what happens after the handler executes: return to the same statement that raised the exception (or the next one) end the block that contains the instruction that raised the exception terminate the program
User-defined exception handlers can appear anywhere in the program (see below) condition is a pre-defined or user-defined exception two built-in conditions are ANYCONDITION and ERROR user-defined exceptions work as follows: ON CONDITION (boolean) SNAP is a keyword to print out dynamic chain Reference environment is the code in which handler is embedded Binding is dynamic: the handler is bound to the exception from the ON statement until either a new handler is defined the end of the local block is reached a revert statement is reached Built-in exceptions all have built-in handlers but can be overridden by user-defined handlers you can enable or disable conditions (some default to being disabled) (NO condition) : statement; or (condition) : statement; Continuation can be a branch (using GO TO) continue with the same or next instr. termination of program PL/I • General form: • ON condition [SNAP] • BEGIN; • … • END;
PL/I Examples In the example below, handlers for Endfile are provided for two different files Above, SIZE is enabled, from the On instruction forward, a handler is defined for any SIZE error (the error handler simply does “SNAP”). The SIZE error handler continues to Operate in B, C, D and E because of dynamic binding (even though only C is inside of B’s static scoping) • Built-in exceptions include ENDPAGE, • ENDFILE, CONVERSION, OVERFLOW, • UNDERFLOW, ZERODIVIDE, SIZE, • STRINGRANGE, SUBSCRIPTRNAGE, • UNDEFINEDFILE
Ada exception handlers are defined using the following syntactic form: when exception_choice { | exception_choice} = > statements when is a reserved word exception_choice is a pre-defined exception type or one defined by the programmer, and statements is a list of statements other is an acceptable choice for exception_choice meaning that this is a default handler for all types of exceptions that do not have specific handlers Handlers are defined in a separate exception portion of a block of code as shown below they can also be listed outside of a subprogram but inside a package Ada begin … code here that can raise exceptions to be handled exception when exc_name1 => handler code here when exc_name2 => handler code here … end;
Binding in Ada • Which handler is executed when an exception arises? • if the block of code has an exception handler for the exception, then the exception is statically bound (that is, the handler in that block is used) • otherwise, the exception is propagated as follows: • if raised in a procedure, exception is propagated to the calling subprogram at the point of the call • if that subprogram has no handler, the exception is propagated to its caller, etc until the exception reaches the main program in which case it is either handled there (if there is a handler) or the program terminates • if raised in a block, the exception is handled by the procedure that contains the block (an example of this follows), and if there is no handler, the exception propagates as described above • if raised in a package body, then the handler of the package is used and if there is none, then it is propagated to whatever unit contains the package declaration • if this is a library, then the program terminates • if the package defines the main program (e.g., not used by another) then the exception is ignored and execution continues!
The block or procedure that raised the exception will be terminated automatically continuation after exception handling either results in termination of the program if there is no handler, or control returns to the body that invoked the unit that raised the exception if Main calls Sub1 and Sub1 raises the exception, after handling, control resumes with the instruction in Main after the call to Sub1 if an exception is raised in a loop, the loop body is terminated, control resumes with the loop control (the loop may be re-entered if the loop condition is true) Other info: exceptions (conditions) can be explicitly disabled there are 5 built-in exception categories: constraint program numeric storage tasking programmers can define further exceptions exceptions can be raised explicitly through raise exception_name Ada Continued
Ada Example exception when End_Error => Put(“Limits Frequency”); for Index in 0..9 loop Limit_1 := 10 * Index; Limit_2 := Limit_1 + 9; if Index = 9 then Limit_2 := 100; end if; Put(Limit_1); Put(Limit_2); Put(Freq(Index+1)); New_Line; end loop; end Grade_Distribution; with Ada.Text_IO, Ada.Integer.Text_IO; use Ada.Text_IO, Ada.Integer.Text_IO; procedure Grade_Distribution is Freq : array(1..10) of Integer := (others => 0); New_Grade, Index, Limit_1, Limit_2 : Integer; begin loop Get(new_Grade); Index := New_Grade / 10 + 1; begin Freq(Index) := Freq(Index) + 1; exception when Constraint_Error => if New_Grade = 100 then Freq(10) := Freq(10) + 1; else Put_Line(“Error – new grade is out of range”); end if; end; end loop;
C++ • Not implemented until after 1990 • handlers are placed in catch blocks following try blocks • if an exception arises in the try block, control can be thrown to the associated catch block • if the code is not in a try block, any exception will not be handled • try and catch blocks are embedded within other code, such as a block or inside a function • example: try { … code with exception … } catch (params) {…} catch (params) {…} • exceptions can only be raised using an explicit throw statement as in throw (params); • NOTE: a throw statement without parameters is possible but only in a handler, the result is that the handler re-invokes itself • the type(s) of parameter(s) determine which catch is used • for instance, throw(x); where x is an int will be caught by a catch(int p); but not by a catch(float p);
If an exception is raised in a try block, the block terminates and control goes to the proper catch catch blocks are checked in order so for instance, if there are two catch blocks that catch an int, the first will be the only one to ever be used a catch that uses (…) for its parameters acts like an else (catches any throw) so it should only be listed at the end of all catch blocks for the given try block if there is no catch to match the throw, then the exception is propagated to the next level or to the function’s caller the process terminates if an exception is propagated to main and there is no handler there Continuation after a handler always returns to the first statement following the last handler in the sequence although a handler could re-invoke itself There are only user-defined exceptions C++’s exception handling is much simpler than Ada or PL/I More on C++
#include <iostream.h> void main() { int new_grade, index, limit1, limit2, freq[10] = {0,0,0,0,0,0,0,0,0,0}; short int eof_condition; try { while(1) { if(!cin >> new_grade) throw eof_condition; index = new_grade / 10; {try { if (index < 0 || index > 9) throw(new_grade); freq[index]++; } catch(int grade) { if(grade = = 100) freq[9]++; else cout << “Error – new grade out of range”; } // catch } // inner try } // while } // outer try catch(short int) { … output for the program goes here } // catch } // main C++ Example
Java • In Java, exceptions are objects • there are already a number of built-in exception classes (all descended from the built-in class Throwable), as well as the facility to define your own exception classes • Throwable has two built-in subclasses: • Error - errors thrown by the Java interpreter such as out of heap memory • Exception - errors thrown by the user program • examples include NullPointerException, EOFException, FileNotFoundException, IOException, ArithmeticException, NegativeArraySizeException, and ArrayIndexOutOfBoundsException • as in C++, the programmer can raise an exception using the throw clause • throw new foo (“Bad news”); • and like C++, there are Try and Catch clauses • try { … } catch (Exception foo) { … } • all Catch’s must have a parameter which must be of a type that is a descendent of the class Throwable
Throwing, Catching, Continuation • Built-in exceptions will be thrown automatically if the exception arises • User-defined exceptions are thrown explicitly through a throw statement (as in C++) • built-in exceptions can also be thrown explicitly • The catch block that catches an exception is based on the type of exception, not on a parameter type • exceptions can be handled in the given block or are propagated if the method explicitly states throws ExceptionType in its header, in which case the exception is propagated to the caller • this can continue until the main program is reached in which case, if not handled, the program terminates
Aside from the throw and catch clauses, Java allows a finally clause The finally clause can be a “clean up” set of code for the object that is, if any exception arises, there might need to be some routine that makes sure the object can continue The finally clause is always executed prior to continuation whether an exception arises or not and regardless of the type of exception Continuation occurs with the statement after the Try construct if there is none, then continuation occurs with the caller of the method and so forth up the run-time stack ultimately, if no method is found, continuation occurs with the original application program or termination A return statement in the handler terminates the method entirely an example similar to the C++ example is given in the book on pages 639-641 Finally, Continuation
Comparisons • In PL/I, exception handling was complicated because • continuation could go anywhere (through GO TO statements) • dynamic binding of handlers to code reduced readability • In Ada, there was an attempt to simplify exceptions • but because of the difference between exceptions being raised in a block, procedure, package or loop, continuation was still complex • In both languages, defining your own exceptions was possible • In C++, exception handling was simplified as much as possible • possibly to the point of making it too weak • since there are no user-defined exceptions, only programmer-specified throw statements • Java seems to have the best (so far) including the finally clause, and capabilities for user-defined as well as system-defined exceptions • C# also has exception handling that are similar to Java except that there is no throws clause for method headers
Event Handling • Event handling can be thought of as a form of exception handling • typically, exception handling is meant to convey that something unexpected arose, handle it • and to prevent run-time error situations from causing program termination • but recall the C++ and Ada programs from earlier, one exception was simply the exception that caused termination of the loop • We can treat other types of events in the same manner • an event is simply the notification that something specific occurred, using with respect to input (mouse motion or button, key entry) • an event handler is the code defined to handle the event • both Java and JavaScript have event handling capabilities although the mechanisms differ from exception handling in Java, they are similarly related