1 / 44

Exception Handling and Assertions

Explore the different types of exceptions, how they are triggered, and the best practices for handling them in programming languages like Java and C++.

sdix
Télécharger la présentation

Exception Handling and Assertions

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Exception Handling and Assertions James Brucker

  2. Exceptions • Exceptions are unusual events detected by the computer or software. • An exception is not necessarily an error. • Asynchronous exceptionscan occur at any time, independent of the program execution. Example: hardware error, user terminates program • Synchronous exceptions occur in response to some action by the program. Example: subscript out-of-bounds, read error, stack overflow Q: Which type of exception can a program "catch" ?

  3. Types of Exceptions • Hardware Errorssuch as write to write-protected devices. • hardware failures are usually fatal • handled by hardware or OS, not application program. • Software Errors including access to invalid memory address, attempt to access non-existent file. • Language Violations(dynamic semantic errors): illegal array subscript, referencing null pointers. • User-defined (program-defined)conditionse.g., a ParseException thrown in a recursive-descent program. Java and C++ allow user to define and raise any "exception".

  4. What triggers exceptions? • Hardware: • hardware may prevent writing to some devices (read-only) • restrict access to memory • OS or Executor: • Java VM detects null reference, I/O, and array bounds errors • OS enforces file permissions • Java Security Manager (raises SecurityException) • User program: • a program can raise or throw exceptions as part of the code (C++, Java, Ada, ...). • a function may "assert" conditions that should be true (for validating the software). If false, an exception is raised.

  5. Exception Handler try { block-of-code; } catch (ExceptionType1 e) { handler-code; } catch (ExceptionType2 e) { handler-code; } ... finally { code to always execute before continuing; } Stringbuffer buffer = new StringBuffer(); try { while ( ( c = System.in.read() ) != 0 ) buffer.append(c); } catch (IOException e) { System.out.println("I/O error: " + e); }

  6. Exception Handler (2) • An exception handler is statically (lexically) bound to a block of code. • Unlike "lexically scoped" variables, the scope of an exception includes any function calls inside its block: try { String line = bufferedReader.readLine( ); writer( line ); } catch ( IOException e ) { System.out.println("I/O error: "+e); }

  7. Two Exception Handling Modes • resumption: after the exception handler runs, the program continues at the point where the exception occurred. • termination: flow of execution branches to exception handler and does not return to the point of exception. try { p = read( fHandle ); process(p); } catch ( exception ) { ... } doSomethingElse( ); Exception raised resumption termination

  8. Exception Propagation • Exception handlers form a stack, each with a scope. • When an exception occurs, the run-time must find an exception handler on the handler stack • it must "unwind" the call stack during the search. sub A( ) { p = new int[-1]; } sub B( ) { try { A( ); } catch( bad_cast ) {...} } sub C( ) { try { B( ); } catch( bad_alloc ) {...} } bad_alloc raised Scopeexceptionhandler 05-07 bad_cast 07 10-12 bad_alloc 10

  9. Exception Handling is Expensive • Runtime environment must locate first handler. • Unwind call chain and stack • locate return address of each stack frame and jump to it. • invoke "epilogue" (return) code for each function • branch to the exception handler • Recommendation: avoid exceptions in normal flow of execution. Example (this is a homework problem): compare the speed of a "factorial" method that uses exceptions and a "factorial" that uses an "if" test to terminate recursion.

  10. Exceptions in Java Exceptions are objects from subclasses of "Throwable". Throwable Exception Error RuntimeException IOException others Detected and thrown by Java VM, such as out-of-heap space • IndexOutOfBounds • NullPointer • ClassCast (bad cast) • many others (see API) • EOFException • ZipException • many others • ParseException • user defined • many others

  11. Exceptions in C++ A C++ program can throw anything. Standard exception classes: exception logic_error runtime_error length_error domain_error out_of_range invalid_argument bad_alloc bad_cast range_error overflow_error underflow_error bad_exception bad_typeid ios_base::failure

  12. Why Use an Exception Hierarchy? 1. Makes exception collection extensible. /** Define an exception for stupid users */ public class StupidUserException extends RuntimeException { public StupidUserException( String msg ) { super( msg ); } }

  13. Why Use an Exception Hierarchy? 2. Programmer can write multiple "catch" blocks arranged hierarchically. // read binary data from a file DataInputStream din = new DataInputStream( ... ); try { count = din.read( bytearray ); processData( bytearray ); } catch ( EOFException eof ) { // no problem ... just close file and continue } catch ( IOException ioe ) { // oops... something wrong err.println("I/O error: " + ioe); } catch ( Exception e ) { // processData( ) threw an exception

  14. Two Types of Exceptions in Java Two categories of exceptions: • Checked Exceptionsare exceptions that Java requires the program to either handle or explicitly acknowledge that it may generate this exception. Example: readData(String filename) throws ...what? • Unchecked Exceptions: the program may provide an exception handler (try ... catch) but is not required. • Unchecked Exceptions are for events that the programmer can avoid by careful programming. • would be tedious to require acknowledging all of them

  15. Checked Exceptions in Java • Checked Exceptions include subclasses of • IOException • CloneNotSupportedException • user-defined classes that extend Exception. • Programmer declares that a method "throws" an exception to a higher-level handler by writing: methodname(params) throwsSomeException readData(String filename) throws IOException { try { URL myurl = new URL("http://www.ku.ac.th"); } catch (MalformedURLException expt) { ... } // other IOException is thrown by readData()

  16. Unchecked Exceptions in Java • Unchecked Exceptions: the program may provide an exception handler (try ... catch) but is not required. • Unchecked Exceptions include subclasses of Error and RunTimeException. • Methods should not use "... throws SomeException" for Unchecked Exceptions. • Reason: • Error conditions are beyond the control of the application. You should let the JavaVM handle them, or • It would be too cumbersome to require every program to either "catch" or "throw" all RunTimeExceptions. For example, every object reference would require declaring or catching "NullPointerException" !

  17. Exceptions Example What exceptions may this Java code throw? /* count the words in a file */ int wordCount( String filename ) { int count = 0; InputStream ins = new FileInputStream( filename ); Scanner scan = new Scanner( ins ); // read input lines while( scan.hasNext() ) { String line = scan.nextLine(); String [] words = line.split("\\s"); // "word" must start with a letter for(int k=0; k<=words.length; k++) if ( Character.isLetter( words[k].charAt(0) ) ) count++; } return count; }

  18. Exceptions Example: Solution If Java required you to declare every exception that a code might throw, this code would look like: /* count the words in a file */ int wordCount( String filename ) throws IOException, NullPointerException, IllegalStateException, NoSuchElementException, ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException { int count = 0; InputStream ins = new FileInputStream( filename ); Scanner scan = new Scanner( ins ); ... }

  19. Rule for RunTimeExceptions You should be able to prevent Runtime exceptions by careful programming. How can you avoid these exceptions? • NullPointerException • ArrayIndexOutOfBoundsException • ClassCastException ClassCastException often indicates faulty program logic. "If it is aRuntimeException, it is your fault!" -- Core Java, Volume 1, p. 560.

  20. Multiple Exceptions • In C and Java a "try" block can catch multiple exceptions. • Exception handlers are tried in the order listed. try { System.in.read(buf); parseLine(buf); } catch (IOException e) { System.out.println("I/O exception "+e); } catch (Exception e) { System.out.println("Unknown exception "+e); } catch (ParseException e) { /* This catch is never reached! */ System.out.println("Parse exception "+e); }

  21. Nested Exception Handlers • You may also nest try - catch blocks. try { try { out = new FileOutputStream("my file"); } catch(FileNotFoundException e) { System.out.println("Error opening file"); throw e; } out.write(buf); } catch (IOException e) { System.out.println("I/O exception "+e); } catch (Exception e) { System.out.println("Unknown exception "+e); }

  22. Propagation of Exceptions Exception are propagated according to the path of execution of a program. int test1() { try { answer = B( ); } catch(Exception e) {...} } int test2() { try { answer = B( ); } catch(Exception e) {...} } int A() { ... throw new Exception("Help!"); } int B() { ... int result = A( ); }

  23. Propagation of Exceptions (2) An exception is propagated to the first enclosing scope that can "catch" the exception. int A(Object obj) { Integer k = (Integer)obj;// ClassCastException return k.IntValue(); } /* B() only catches IOException */ int B(Object obj) { try { result = A(obj); } catch (IOException e) { /* do something */ } } /* C() catches any RuntimeException */ int C() { try { result = B("10"); } catch (RuntimeException e) { ... }

  24. Propagation of Exceptions (3) • If the application program does not provide an exception handler, then a default exception handler is used. • In Java, the default exception handler: • prints name of exception and where it occurred • prints stack trace • terminates the program • In C++, method terminate() is invoked • programmer can specify his own method using set_terminate( )

  25. Exceptions in C++ • An exception can be any type! • Exceptions can be programmer defined or exceptions from the C++ standard library. struct Error { } e; try { if ( n < 0 ) throw n; else if ( n == 0 ) throw "zero"; else if ( n == 1 ) throw e; } catch (int e1) { cout << "integer exception raised" << endl; } catch (string e2) { cout << "string exception " << endl; } catch (Error e3) { cout << "struct Error" << endl; }

  26. Exceptions in C++ Class Hierarchyinclude file exception <exception> bad_alloc <new> bad_cast <typeinfo> bad_exception <exception> bad_typeid <typeinfo> failure <ios> logic_error (has subclasses) <stdexcept> runtime_error (has subclasses) <stdexcept> • bad_exception is a generic type for unchecked exceptions.

  27. Exception Handler in C++ • Example: catch failure of "new". #include <iostream> using namespace std; using std::bad_alloc; char *makeArray(int nsize) { char *p; try { p = new char[nsize]; } catch ( bad_alloc e ) { cout << "Couldn't allocate array: "; cout << e.what( ) << endl; p = null; }

  28. Declaring exceptions • To declare that your function throws an exception: #include <iostream> using namespace std; using std::bad_alloc; char *makeArray(int nsize) throw(bad_alloc) { char *p; try { p = new char[nsize]; } catch ( bad_alloc e ) { cout << "Couldn't allocate array: "; cout << e.what( ) << endl; throw; // re-throw bad_alloc exception }

  29. Declaring no exceptions • To declare that your function throws no exceptions: #include <iostream> using namespace std; using std::bad_alloc; char *makeArray(int nsize) throw() { char *p; try { p = new char[nsize]; } catch ( bad_alloc e ) { cout << "Couldn't allocate array: "; cout << e.what( ) << endl; return NULL; }

  30. Exception Handler in C++ • A function can have multiple "catch" blocks. int main( ) { try { sub(); /* sub() throws exceptions */ } catch ( bad_alloc e ) { cerr << "Allocation error " << e.what(); } catch ( exception e ) { cerr << "Exception " << e.what(); } catch ( ... ) { //"..." matches anything: this catch // block catches all other exceptions cerr << "Unknown exception " << endl; }

  31. Rethrowing an Exception • A function can throw an exception it has caught: int main( ) { //... other code goes here ... try { sub(); /* sub() that throws exceptions */ } catch ( bad_alloc e ) { cerr << "Allocation error " << e.what(); throw; }

  32. C++ Default Exception Handler • If an exception is not caught, C++ provides a default exception handler: • If the function didn't use "throw(something)" in its header, then a method named terminate() is called. • If a function declares exceptions in its header, but throws some otherexception, then the function unexpected() is called. unexpected() also calls terminate(). • unexpected() in implemented as a pointer. You can change it to your own exception handler using: set_unexpected( your_function ) • Similarly, use set_terminate() to replace terminate() with some other function. • Prototypes for set_unexpected() and set_terminate() are defined in the header file <exception>.

  33. C++ Default Exception Handler #include <exception> void my_terminator() { cerr << "You're terminated!" << endl; exit(1); } void my_unexpected() { cout << "unexpected exception thrown" << endl; exit(1); } int main() throw() { set_unexpected(my_unexpected); // ignore return value set_terminate(my_terminator); for(int i = 1; i <=3; i++) try { f(i); } catch(some_exception e) { cout << "main: caught " << e.what() << endl; throw; }

  34. Exception Handling is Expensive Actual student code to find a tree node matching string: class Node { String value; Node left, right; // branches of this node /** find a node that matches the string arg */ Node find( String arg ) { Node node; int compare = value.compareTo(arg ); if (compare == 0) return node; try { if (compare > 0) return left.find(arg ); if (compare < 0) return right.find(arg ); } catch ( NullPointerException e ) { return null; }

  35. Exception Handling is Expensive More efficient to write code that avoids exceptions: class Node { String value; Node left, right; // branches of this node /** find a node that matches the string arg */ Node find(String arg ) { Node node; int compare = value.compareTo( arg ); if (compare == 0) return node; if (compare > 0 && left != null) return left.find( arg ); else if (compare < 0 && right !== null) return right.find( arg ); else return null; }

  36. Exception Questions • Do exception handlers use lexical or dynamic scope? • What is the purpose of "finally { ... }" ? • What language introduced exception handling? • Efficiency: see homework problem.

  37. Ordering of catch blocks try { /* What is wrong with this code? */ y = func(x); } catch ( exception ) { cerr << "caught exception"; } catch ( bad_alloc ) { cerr << "caught bad_alloc"; } catch ( ... ) { cerr << "what's this?"; } catch ( logic_error ) { cerr << "Your Error!!"; } try { /* What is wrong with this code? */ System.in.read(buf); /* throws IOException */ } catch ( Exception e ) { /* A */ System.err.println("Exception "+e); } catch ( IOException e ) { /* B */ System.err.println("IO exception "+e); }

  38. Assertions • Assertions are logical tests that should always be true at a given point in a program. • Programmers use assertions to help verify program correctness during development. • If an assertion is false, an exception is raised. • After the program is completed, assertions can be disabled using a compiler option, so they do not effect "production" code -- but are still available to the developer. • Both C++ and Java support assertions.

  39. Use of Assertions Assertions are used in methods to specify: Pre-conditions: conditions that should always be true when the method is invoked Post-conditions: conditions that should be true when the method returns class Node { String value; Node left, right; /** find a node that matches the string arg. * @precondition value is not null */ Node find(String what) {

  40. Assertions Example Move discs from one stack to another stack in Towers of Hanoi game. Preconditions: • the "from" and "to" stacks are not null • the "from" stack must not be empty (has a disc) Postcondition: • the "to" stack contains at least one disc

  41. Assertions Example void MoveStack(Stack fromStack, Stack toStack) { // stacks should not be null! assert fromStack != null : "from stack is null"; assert toStack != null : "to stack is null"; // fromStack should not be empty assert fromStack.size() > 0 : "from stack empty"; ... code goes here // PostCondition: toStack not empty assert toStack.size() > 0 : "to stack is empty"; }

  42. Enabling Assertions • You must enable assertions in order to activate them java -ea java -ea:[packagename...|classname...] • This enables programmer to leave assertions in the source code (for development) without affecting users of the program. • if not "enabled" (-ea), then the assert code is not run. • in Java 1.4 you must also use "-ea" with javac to compile assertion code.

  43. "assert" versus "throw AssertionError" "assert" will throw an AssertionError. • You can use "assert" ... • or, throw an AssertionError ... • Are these two equivalent? void push(Object obj) { // stack should not be null! assert stack != null : "Stack is null"; void push(Object obj) { // stack should not be null! if ( stack == null ) throw new AssertionError("Stack is null");

  44. "assert" in other languages • how to emulate assertions in C: /* myheader.h */ #define DEBUG 1 /* 0 for production version */ #include <myheader.h> #if DEBUG if ( fromStack == null ) fprintf(stderr, "fromStack is null"); #endif

More Related