dis/assemblering_maniac

Thursday, September 30, 2004

INTRODUCTION TO EXCEPTION HANDLING

INTRODUCTION TO EXCEPTION HANDLING PART 1 - A SIMPLE EXAMPLE

In this and subsequent issues we will be discussing some aspects of
C++ exception handling. To start this discussion, let's consider a
simple example. Suppose that you are writing a program to manipulate
calendar dates, and want to check whether a given year is in the 20th
century (ignoring the issue of whether the 21st century starts in 2000
or 2001!).

Using exceptions, one way to do this might be:

#include

class DateException {
char* err;
public:
DateException(char* s) {err = s;}
void print() const {cerr << err << endl;}
};

// a function that operates on dates
void g(int date)
{
if (date < 1900)
throw DateException("date < 1900");
if (date > 1999)
throw DateException("date > 1999");
// process date ...
}

// some code that uses dates
void f()
{
g(1879);
}

int main()
{
try {
f();
}
catch (const DateException& de) {
de.print();
return 1;
}

return 0;
}

The basic idea here is that we have a try block:

try {
f();
}

Within this block, we execute some code, in this case a function call
f(). Then we have a list of one or more handlers:

catch (DateException de) {
de.print();
return 1;
}

If an abnormal condition arises in the code, we can throw an exception:

if (date < 1900)
throw DateException("date < 1900");

and have it caught by one of the handlers at an outer level, that is,
execution will continue at the point of the handler, with the
execution stack unwound.

An exception may be a class object type such as DateException, or a
fundamental C++ type like an integer. Obviously, a class object type
can store and convey more information about the nature of the
exception, as illustrated in this example. Saying:

throw -37;

will indeed throw an exception, which may be caught somewhere, but
this idiom is not particularly useful.

What if the handler we declare is changed slightly, as in:

catch (DateException* de) {
de->print();
return 1;
}

In this case, because an object of type DateException is thrown,
rather than a DateException* (pointer), no corresponding handler will
be found in the program. In that case, the runtime system that
handles exception processing will call a special library function
terminate(), and the program will abort. One way to avoid this
problem is to say:

main()
{
try {
body_of_program();
}
catch (...) {
// all exceptions go through here
return 1;
}

return 0;
}

where "..." will catch any exception type.

We will explore various details of exception handling in future
issues, but one general comment is in order. C++ exceptions are not
the same as low-level hardware interrupts, nor are they the same as
UNIX signals such as SIGTERM. And there's no linkage between
exceptions such as divide by zero (which may be a low-level machine
exception) and C++ exceptions.

0 Comments:

Post a Comment

<< Home