l7: exceptions problem description error handling –terminate the program –return a value...

25
L7: Exceptions Problem Description Error Handling terminate the program return a value representing an error return a legal value and leave the program in an illegal state call an error-handling routine use exceptions Use inheritance to implement exceptions Resource Management Typeid Chapter 8 and 14 of Stroustrup

Upload: isaiah-maynard

Post on 26-Mar-2015

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

L7: Exceptions• Problem Description

• Error Handling

– terminate the program

– return a value representing an error

– return a legal value and leave the program in an illegal state

– call an error-handling routine

– use exceptions

• Use inheritance to implement exceptions

• Resource Management

• Typeid

• Chapter 8 and 14 of Stroustrup

Page 2: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Exceptions

• See Chapter 8 and 14 of Stroustrup• Library or class can detect run-time errors,

but may not know what to do with them.• Caller may know what to do with run-time

error, but doesn't know how to detect them.• What can be done?

Page 3: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Error Handling

• Possibilities include:– terminate the program

– return a value representing an error

– return a legal value and leave the program in an illegal state

– call an error-handling routine

– use exceptions

Page 4: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Terminate Program

• Default behaviour for uncaught exceptions in C++

• Not appropriate for libraries

Page 5: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Error Value Return

• Often no plausible error value• Inconvenient because error must be checked

for every function call

Page 6: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Illegal State

• Behaviour of C library functions• Global variable “errno” is set by library. • Calling routine must explicitly check errno.

Page 7: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

#include <cstdio>#include <cstdlib>#include <errno.h>

int main() { //if error, fopen returns NULL and sets errno FILE * f = fopen("filename", "r");

if (!f) // an error has occurred, check errno {

// file doesn't exist if (errno==ENOENT) printf("No file\n");

// perror checks errno and prints message perror("An error occurred opening file"); exit(-1); }}

Page 8: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Error Handling Routine

• Exceptions not meant to handle this case• But error handling routine has to choose a

mechanism for dealing with errors

Page 9: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

#include <csignal>#include <cstdio>#include <cstdlib>

void sighandler(int sig){ printf("received signal %d\n", sig); exit(-1);}

int main(){ // register the handler with a seg fault signal(SIGSEGV, sighandler);

// do something to cause a seg fault delete (int*)-10;}

Page 10: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Exceptions

• Designed to support handling of errors and other exceptional conditions

• Non-local control structure based on stack unwinding

• An alternative to the usual return mechanism• Some legitimate uses that are not related to

errors

Page 11: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Stack Unwinding

When an exception is thrown and control passes from a try block onto a handler, the C++ run time calls the destructors of all the automatic objects constructed since the beginning of the try block. This process is called stack unwinding.

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp

Page 12: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Exceptions

• Exceptional does not necessarily mean– “almost never happens”, or

– “a disastrous event”.• Can be thought of as:

– “some part of the system couldn't do what it was asked to do”

• So, don't use exceptions when errors can be handled locally.

Page 13: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Throw

struct RangeError {

int i;

RangeError(int ii){i=ii;};

};

char to_char(int i) {

if (i < numeric_limits<char>::min() || i > numeric_limits<char>::max())throw RangeError(i);

return (char)i;

}

Page 14: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Catch

void g(int i) {

try {char c = to_char(i);// ...

} catch (RangeError r) {cerr << “can't convert “ << r.i << “ to char\n”;

}

}

Page 15: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Inheritance and Exceptions

class Matherr {};

class Overflow : public Matherr {};

class Underflow: public Matherr {};

class Zerodivide: public Matherr {};

void f() {

try { // ... }

catch (Overflow) {// handle overflow};

catch (Matherr) {// handle any other Matherr};

catch (...) {// handle any other exception};

}

Page 16: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Resource Management

void use_file(const char *fn) {

File *f = fopen(fn, “r”);

try {// use f

} catch (...) {fclose(f);throw;

}

fclose(f);

}

Page 17: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Resource Allocation is Initialisation

class FilePtr {

private: FILE *p;

public:FilePtr(const char *name, const char *a){p = fopen(name, a);};~FilePtr(){if (p) fclose(p);};

};

Page 18: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Resource Allocation is Initialisation

void use_file(const char *p) {

FilePtr f(p, “r”);

try {// use f

} catch (...) {// handle exception

}

}

Page 19: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

typeid Given an object (or a variable), typeid

operator retrieves the type of an object (or a variable) to which a pointer or a reference points.

Can be used to discover things about the actual type (usually its name).

An alternative to dynamic_cast.

Page 20: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Inheritanceclass Shape { public: virtual void draw() = 0;};class Rectangle: public Shape { public: void draw() { cout << "draw a rectangle\n";};

};class Circle : public Shape { public: void draw() { cout << "draw a circle\n"; };

};

Page 21: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Example 1: An Alternative to Downcasting

void rotate(const Shape &shape) {

if (typeid(shape)==typeid(Circle)) {

cout << "rotate Circle\n";

} else if (typeid(shape)==typeid(Rectangle)) {

cout << "rotate rectangle\n";

}

}

Circle c;

Rectangle r;

rotate(c); // rotate Circle

rotate(r); // rotate Rectangle

Page 22: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

In the case of a polymorphic class (containing pure virtual functions), the typeid operator retrieves the most derived type of this object, if the argument of the typeid is an object (pointed by a pointer).

If the argument is a pointer itself, the typeid operator regards the type of this object as the pointer of this class.

Example 2

Page 23: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

void f(Shape &circle, Shape *rectangle) {

if(typeid(circle) == typeid(Circle))

cout << "a is of type Circle\n";

if(typeid(*rectangle) == typeid(Rectangle))

cout << "a is of type Rectangle\n";

Shape *s;

if(typeid(rectangle) == typeid(s))

cout << "a is of type Shape\n";

}

int main() {

Circle c;

Rectangle r;

f( c, &r );

}

Example 2

Page 24: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Example 3

In the case of a non-polymorphic class, the typeid operator retrieves the type of the object given.

class C {

public:

C() {};

};

class D : public C {

public:

D() {};

};

Page 25: L7: Exceptions Problem Description Error Handling –terminate the program –return a value representing an error –return a legal value and leave the program

Example 3

D d;

C *c1 = &d;

C &c2 = d;

cout << "c1: " << typeid(*c1).name() << endl; // C

cout << "c2: " << typeid(c2).name() << endl; // C