28
Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component errors Class might perform incorrectly invalid array index Pop() empty stack

Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Embed Size (px)

Citation preview

Page 1: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Exception Handling Programmers must deal with errors

and exceptional situations: User input errors Device errors

Empty disk space, no memory Component errors

Class might perform incorrectly invalid array index Pop() empty stack

Page 2: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Handling errors Most errors are unpleasant to handle The programmer should not just abort

the program with an assertion failure; the user may lose all work performed during the program session

Instead, the program must do the best it can to recover, and exit gracefully, only if it is really necessary.

Page 3: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Reaction to error Conditions Returning an error code

#define FILE_OPEN_ERROR 1#define OK 0

int openMyFile() {FILE * f = fopen(“File.txt”, “r”);if ( f == NULL )

return FILE_OPEN_ERROR;else

/* Do things to a file*/…return OK;

}

Advantage: simple to implementDisadvantage: Code contains a lot of error checking

Page 4: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Do nothing Ignore error condition

Common approach Simpler to code

Hard to debug Program might terminate or abort or produce

incorrect answer Location of original problem might be hard to find Can use assert() in the debug mode Can be misleading to the caller.

void Stack::push() will not push element when stack is full, however, the caller will think he successfully pushed element on the stack

When coping fails, can not simply ignore the problem

Page 5: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Setting an Error Variable You keep a global variable, such as errno Whenever function returns, you can check errno variable

if there was an error when executing the function Simple to implement Code still contains a lot of error handling code, ie:

if ( errno == ERROR_NO_5 ) { printMessage(ERROR_NO_5);} The error report contains only the type of error, not the

name of the offending function Two errors in rapid succession will result in the first one

being overwritten Also a problem with multithreaded functions using the same

variable

Page 6: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Printing an Error Message Reasonable in debugging mode only Simple Impacts reusability

Defeats the purpose of programmatic handling of error conditions

No control of program flow After error is printed, the program continues

Does not always make sense to the user Example: “System error 0xff4ff45”

Page 7: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Aborting the Program Good for fatal error Good for debugging purposes Undesirable loss of all volatile data

accumulated throughout program’s life time

Page 8: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Jumping to an error handler Non-local jump

C setjmp() and longjmp() Provides centralized error handler Do not have to worry about stack

unwinding Good approach for C programs, BAD for C+

+ programs When longjmp() leaves stack of the function, no

destructors are called for the objects allocated on the stack.

Page 9: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Raising a Signal Explicitly creates Software Interrupt by

calling function raise() and specifying interrupt handler

Good for hardware interface Memory fault Segmentation violation

Bad for typical error handling, signals should only be used for their intended purpose

Page 10: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Raising an Exception C++ has a convenient and safe

mechanism to raise exceptions when errors are detected and to transfer both control and error information to code that is competent to deal with the situation

Handles stack unwinding Calls destructors Enables a block of code to be protected Cut down on error handling code

Page 11: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Exceptions Exceptions are the proper way to bail

out of a situation which cannot be handled easily by a function itself, but which are not disastrous enough for the program to terminate completely.

Exceptions provide a flexible layer of flow control between the short-range return and the crude exit()

Page 12: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

C++ exceptions When an error is encountered that

cannot be handled at the point of detection, an exception can be raised with the command:

throw e; Where ‘e’ could be an object, structure, or simple data type.Simple data types are not useful:throw 1; throw “Stack underflow”

Page 13: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

C++ Exceptions The try block surrounds statements in which

exceptions may be generated Example:

try{

// Statements in which exceptions// may be thrown

} The throw statement should be executed

somewhere within the try-block: either directly or from within a function called directly or indirectly from the try-block

Page 14: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Catch The “catch” keyword immediately follows

the try-block Catch-block receives the thrown

exceptions. Example

try {read();

} catch( StackError s){

// Report syntax error in the input file, and close file}

Page 15: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Throwing exceptions in C++ Local objects should not be thrown, nor should pointers to

local objects be thrown However, it is possible to throw pointers or references to

dynamically generated objects, taking care that the generated object is properly deleted when the generated exception is caught

Example:

try{throw new Exception();

}catch( Exception * e) {

// process edelete e; // deallocate dynamically created object

}

Page 16: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Throwing references We could thrown referencestry {

throw *new Exception();}catch( Exception & e) {

// Process edelete &e;

}

Page 17: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Catching references / Safe This is totally safe

try {throw Exception(); }

catch(Exception & e) {//

}Output:

Exception() constructor is calledcatch block is processed~Exception() is called when reach end of catch-block

Page 18: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Catching exceptions / Unsafe This is not always safe depending on the nature of

Exception destructortry {

Exception e;throw e; }

catch(Exception & e) {//

}Output:

Exception() constructor is called~Exception() destructor is calledcatch block is processed~Exception() is destructor is called the second time

- Potential problem of double deallocation

Page 19: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Handling multiple exceptions A try block can throw different

types of exceptionstry { /* code */ }catch( StackError & s ) { // Process StackError}catch(MathError & m ) {

// Process MathError ) }

Page 20: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

rethrow Occasionally, we want to catch any exceptions that fly

past a certain point, just to take some cleanup or protective actionstry { /* … */ }catch( … ) { /* evasive action */throw;

}The throw command without an argument in-side a catch

clause throws the current error again Errors that current function does not know how to

handle must be re-threw

Page 21: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Declaration of exception throwers The declaration of a function that may throw one or

more exceptions:void exceptionThrow() throw(char *, int);

This function may throw char * and int exceptions Note, declaration of exceptions is not mandatory

However, it declared, it notifies the user of a function that this function may throw certain exceptions, which need to be handled

Without a function throw list all responsibilities of providing the correct handlers is in the hands of the designer of the program

Page 22: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Derived exceptions Lets assume class D derives from

class B and exception of type D is thrown, then we can catch exception D using catch(B) {

/* Catch exception B and any classes deriving from it */}Note: Catch block can only specify the type

Page 23: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Stack unwinding The process of searching “up though

the stack” to find a handler for an exception is commonly called “stack unwinding”

All objects on the stack between the throw and catch point are properly destroyed by invoking their destructors This activity is of crucial importance, it is

guaranteed that all destructors of abandoned stack objects are invoked thus preventing memory leak

Page 24: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Stack unwinding

main()

a()

b()

c()

d()

e()Top of the stack

throw Exception

Catch Exception

Stack unwinds starting from function e(), d(), and c(). Destructors are called in e(), d(), and c() as stack unwinds, until exception is caught at b()

Page 25: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Destructors and uncaught exceptions Uncaught exceptions cause

program Abort and exit Destructors should not throw

exceptions If a destructor that is invoked while

an exception is pending itself raises an exception, the program terminates

Page 26: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

Exception advices Don’t throw exceptions from libraries

Customers will not know that they need to catch an exception

When they catch an exception they will not know how to handle it

If you have to throw an exception, specify it in the prototype of the function This makes the user of the function aware that

he might need to catch an exception Never throw exceptions to return the result

of computation.

Page 27: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

What exceptions should you throw? Failure of precondition Resource limitation Device failure Subsystem failure

Page 28: Exception Handling Programmers must deal with errors and exceptional situations: User input errors Device errors Empty disk space, no memory Component

More advice Catch those exceptions that you can

handle Catch and rethrow exceptions that you

can partially handle If possible, don’t use pointers and

handles on the stack but place then inside objects with proper destructors

Don’t throw an exception if you can continue