exceptions. n programmers have traditionally ignored the proper dedication of attention to error...

26
Exceptions

Post on 21-Dec-2015

212 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Exceptions

Page 2: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Exceptions

Programmers have traditionally ignored the proper dedication of attention to error handling

Enclosing code inside countless nested-ifs is not an attractive approach

This approach is not perfect either. It does minimize the attention you (the

programmer) have to give to errors once the appropriate infrastructure has been established.

Once again it has subtleties which require the programmer to be careful.

Should be used sparingly on MAJOR errors.

Page 3: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

EXCEPTIONal circumstances

Determining WHEN to use exceptions is difficult and subjective.

Most authors tend to agree that they are to be used in exceptional circumstances– memory allocation problems– input file incorrectly formatted– dividing by zero– removing from an empty stack

In the first example, a rational number class will be examined. The primary errors here may not be exceptional but will serve to indicate the principles.

Page 4: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Current approaches include

Use the assert macro to display an error

char* newstring = char[stringlen+1];

assert(newstring != NULL);

-> Assertion failed: newstring != NULL;

Surrounding with an if if (newstring ==NULL) {...; exit(-1);}

..... For classes, you can install an error

handler as shown on p. 313 of Horstmann. (considered later)

Page 5: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

THREE basic partsof exceptions

TRY - a block of code in which exceptions can occur

THROW - a call to an exception handler

CATCH - a routine to handle the problem

Example:try{ // code causes error .... throw Error1; // int }catch(int code){ ...// handle error }

try{ .. if(condition) throw ... }

catchhandler{ handle & stop or continue }

EXIT

Page 6: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Simple example

char inputint;

cin >> inputint;

try {

if (!isalpha(inputint))

throw (int) inputint;

...... // process normal char

}

catch(int errorval) {

inputint = FILLCHAR; }

// here ignore errorval

// continues execution

CLEARLY THIS WOULD BE HANDLED ANOTHER WAYBUT IT REPRESENTS A SIMPLE EXAMPLE

Page 7: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Multiple handlersare used in order and by

type

char inputint;

cin >> inputint;

try {

if (!isalpha(inputint))

throw (int) inputint;

else

throw inputint;

}

catch(int errorval) { // catch must immed follow try

cout << “Error int ” << errorval << endl; ... }

catch(char errorval) {

cout << “Good char ” << errorval << endl; }

5Error int 5

68Good char D

Page 8: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Flow control:throw or f(x) which throws

try { ...... throw or f(x) more statements in try } catch( ) { statements; exit or throw or neither } statements

f(x) { ...... throw ..; other statements in f(x); }

PROGRAM EXITS

To an enclosing nestedtry..catch.I.e. forward the errorto another handler.

more statements in try &other statements in f(x);MAY NOT EXECUTE!

Page 9: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Better example class Ratnl { private: long n; long d; public: Ratnl(long,long); Ratnl(long);};

Ratnl::Ratnl(long a,long b){if (a==0) throw(RatnlExcept(ZeroNum)); if (b==0) throw(RatnlExcept(ZeroDen));n=a; d=b; }

enum RatnlErr{enum RatnlErr{ ZeroNum, ZeroDen;};ZeroNum, ZeroDen;};

class RatnlExcept{class RatnlExcept{ RatnlError err;RatnlError err; public:public: RatnlExcept(RatnlErr c)RatnlExcept(RatnlErr c) { err = c;}{ err = c;} void Response()void Response() {switch (err){switch (err) case ZeroNumer:case ZeroNumer: cout << “0 Numer\n”; cout << “0 Numer\n”; break;break; case ZeroDenom:case ZeroDenom: cout << “0 Denom\n” }cout << “0 Denom\n” }};};

From WORX text The Beginner’s Guide to OOP Using C++by Romanovskaya, et all

Page 10: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

The main routine

void main()

{ ....

try

{ Rational r(3,4);

Rational s(7,0);

cout << “Construction done!”;

}

catch (RatnlExcept & r)

{

r.response();

}

cout << “End of Program\n”;

}

OUTPUT:0 DenomEnd or Program

NOTE: The programmer decided to catch the error. Failure to catch is also a problem.

Page 11: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

The throw statement

IMPLICIT THROW : You call a routine which throws an exception. If you have the call within a try block, the catch associated with the try containing the call may handle the error. (The main routine overhead)

– The called routine CAN catch the error.– If it does, it can also choose to throw the error

to an enclosing catch handler.» p. 318» rethrow same exception with no parameters

• throw;

EXPLICIT THROW: The try itself call throw. (Simple example overhead)

Page 12: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

The catch function

Catch function must match parameters Catch functions are used from the

innermost to outermost try blocks. Note the try blocks are dynamically

defined Within a block, the order (matching) is the

physical order. The first parameter match found is the one

used (first). Catch can have (...) ellipses for parameters

– This handler matches ANY call

Catch can have NO type: only handles no parameter.

Page 13: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

#include <iostream.h>

void main() { int t=5; try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl;} cout << "Program done\n"; }

OUTPUT :Value caught was 3Program done

Page 14: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

#include <iostream.h>

void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl;} } catch (int x) {cout << "Value caught OUTER was " << x << endl;} cout << "Program done\n"; }

OUTPUT:Value caught was 3Program done

Catch function IS NOT CALLED !

Page 15: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; // THROW IT TO OUTER HANDLER } } catch (int x) {cout << "Value caught OUTER was " << x << endl;} cout << "Program done\n"; }

OUTPUT:

Value caught was 3Value caught OUTER was 3Program done

Page 16: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

void main(){ int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; // THROW IT TO OUTER HANDLER } catch (...) {cout << "In Catchall" << endl; throw;} } catch (int x) {cout << "Value caught OUTER was " << x << endl;} catch (...) {cout << "In SECOND Catchall" << endl;} cout << "Program done\n"; }

OUTPUT:Value caught was 3Value caught OUTER was 3Program done

NEITHER (...) functionsare used even with throw;Only one of the handlersis used at a level.

Page 17: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

void main() { int t=5; try { try { if (t==5) throw 3; cout << "No error\n"; } catch (int z) {cout << "Value caught was " << z << endl; throw; } catch (...) {cout << "In Catchall" << endl; throw;} } catch (int x) {cout << "Value caught OUTER was " << x << endl; throw; // THROW IT TO OUTER HANDLER } catch (...) {cout << "In SECOND Catchall" << endl;} cout << "Program done\n"; }

OUTPUT:Value caught was 3Value caught OUTER was 3Abnormal program termination

The last throw couldNOT be caught andresulted in termination!

Page 18: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

catch(...)

Always use catch(...) last

try

{ ---------- }

catch (...)

{ -------- }

catch ( int x )

{ -------- } The last handler will never be used

because the first handler will always catch the exception.

Page 19: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Control over who throws

Any exception thrown but not caught results in abnormal program termination!

You want knowledge (minimally) and control (optimally) over who throws.

resulttype f(parameters) throw (throwlist);

Ratnl f(long x, long y) throw (RatnlExcept);

This determines what exceptions can be thrown by this function!... a throwlistAny other throw results in program termination.

throw()as a throwlist intercepts the throw and does not allow it outside the function,but short-circuits straight to program termination, unlessthe function ITSELF has acatch for the throw.

Page 20: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Types of exceptions If an exception occurs which is not listed in the throw list ->

UNEXPECTED EXCEPTION– c++ has a function unexpected() which handles the error.

– you can redefine it.

» Yours-> void myunxp();

{ ... ; terminate(); // called by system one}

» call -> set_unexpected(myunxp); If no matching handler is found -> UNHANDLED EXCEPTION

– Normally calls terminate(); as shown above

– redefine by

» call -> set_terminate(myterminate);– your terminate() should call either

»exit() or abort()

Page 21: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Constructors and Destructors

If the code is skipped in a try block, what about the destructors?

When an exception is thrown inside a try block, the destructor for each and every object created in the try block is called before the catch handler gets control.

class Ratnl{ ... ~Ratnl() // destructor { cout << “Rat done!” << n << ‘/’ << d << ‘\n’;} };

void main() { try { Ratnl r(3,5); Ratnl s(2,0); } ... }

OUTPUT:...Rat done 3/5

Page 22: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Where should try begin/end?

Considering the constructor/destructor issue:

Consider the group of items which are involved in an operation

Declare objects in the try block when possible.

When the operation fails, destructors are automatically called. Some can, others can’t.fs istream;

fs.open(“datafile”);g(fs); // causes exceptionfs.close(); // not called

fs.open(“datafile”);try { Employee e; f(fs);}catch(...) { fs.close(); throw; }fs.close();

NOTE: in this example, fs COULD be placed inside

Page 23: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Catch routines with references to base/derived

classes

Given a base class B and derived class D: Assume that each class has a routine

defined for you to use as a catch routine (part of the class).

catch ( B& b)

{ ..... }

catch ( D& d)

{ ..... } Can the second ever be reached?

NO. A B reference will use the first

A D reference will be converted to a B reference

Page 24: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

A Design Strategy

When designing your own class libraries provide the programmer an opportunity to supply a handler.

Here I use the term handler to indicate routine which throws not the routine which catches.

P.313 Stack shows how to– define a default handler– let the programmer set their own handler– let the programmer reset the handler to the original– user version can only access public info

The default handler can throw exceptions The programmer substituted handler can

avoid throwing the error.

Page 25: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Static Member Functions

Static member functions in Stack:

Function is for the whole class “this” is not available only static data members and static

functions can be accessed

Page 26: Exceptions. n Programmers have traditionally ignored the proper dedication of attention to error handling n Enclosing code inside countless nested-ifs

Design Suggestions

Don’t catch it if you can’t handle it. Don’t use exceptions for simple errors

easily handled with direct code. You want to continue if possible. Avoid

throwing if you can continue from where you are.

Give users of libraries some control over handlers

Package items in the try section to be in objects which have properly defined destructors so that they are properly disposed in the event of exceptions thrown.