Exception Handlers in C

utzoo!decvax!harpo!ihps3!ihuxf!dunk utzoo!decvax!harpo!ihps3!ihuxf!dunk
Thu Oct 28 15:35:37 AEST 1982

Someone has recently suggested the use of setjmp/longjmp in C programs
as a substitute for exception handlers as present in modern languages
like ADA, MESA, CLU, etc.  Having never used setjmp/longjmp, I thought
it might be fun to try them in an approximation of ADA exception handlers:

    1)	The main program prepares to "catch" all exceptions, i.e. provide
	a default error handler, by calling setjmp(env).  The return value
	(zero in this case) is used as the selector of a switch statement;
	non-zero return values indicate that an exception has been caught.

    2)	Whenever a routine notices an error, it can "raise" an exception
	by calling longjmp(env, val), where val is the type of exception.
	Control will be passed to the most recent caller of setjmp; it will
	appear as if setjmp has returned the value val.  The caller of setjmp
	then handles the error, automatically aborting any subfunctions.

    3)  Should a function wish to "catch" an error locally, it simply
	remembers the current value of env, and calls setjmp(env).  If an
	error is caught, it can either be handled, or the error can be
	propagated back by restoring the old env, and calling
	longjmp(env, retval), where retval is the exception type returned
	by setjmp.  Also, should this function return control normally, it
	must remember to un-catcth exceptions (i.e. restore the old env).

This might work, but it certainly relies on a lot of incantations.  In
very large projects, where exception handling is an important issue, the
programming staff is often unexperienced with "normal" programming practices,
much less incomprehensible invocations of setjmp/longjmp.  What good is
exception handling if it creates exceptions as often as it handles them?

Also, as sketched out above, it is impossible for an exception handler to
decide to return to the point of exception (ADA doesn't allow this either,
but MESA does).  Furthermore, consider real-time behavior.  A good
implementation of exception handlers only incurs real-time when an exception
is raised; setjmp/longjmp pays whenever arrangements are made to catch an
exception.  Also, it is not clear to me how setjmp/longjmp interacts with
hardware/OS raised exceptions.  It is also not clear to me how "real"
exception handlers would fit into C.

As a related point, what are peoples feeling about C's philosophy of
little compile-time and run-time checking.  Back in school, when I used
PASCAL to write programs more complex than I write now with C, I found
that my programs were 80% debugged by the time they compiled.  The remaining
20% was usually trivial since I would usually receive immediate indication
of the error (e.g. array index out of bounds, NIL or unassigned pointer
dereference, etc.).  With C, compilation is usually a snap (though it is
easy to puzzle over a "syntax error" message), but debugging often leads
to mysterious "bus error - core dumped" types of messages.

Now, I understand that one of C's reasons for not doing much checking
is to save real-time during program execution, which I suppose is
justifiable.  Unfortunately, in my experiences with those very large
projects I alluded to earlier, I find that, for "system reliability",
I must insert almost the same checks that a good compiler would
(assuming this compiler could optimize out the redundant checks).  Surely
manual array bounds-checking in C programs is less efficient than a
compiler that has access to nifty instructions.  Maybe I'm wrong.

Tom Duncan
Bell Labs

More information about the Comp.lang.c mailing list