Re: Exception Handling

"Fergus Henderson" <fjh@cs.mu.OZ.AU>
14 Aug 2002 02:20:41 -0400

          From comp.compilers

Related articles
[3 earlier articles]
Re: Exception Handling jacob@jacob.remcomp.fr (jacob navia) (2002-07-24)
Re: Exception Handling david.jobet@ng-market.com (David Jobet) (2002-07-25)
Re: Exception Handling journeyman@compilerguru.com (journeyman) (2002-08-04)
Re: Exception Handling nmm1@cus.cam.ac.uk (Nick Maclaren) (2002-08-10)
Re: Exception Handling marcov@toad.stack.nl (Marco van de Voort) (2002-08-10)
Re: Exception Handling max1@mbank.com.ua (Maxim Reznik) (2002-08-10)
Re: Exception Handling fjh@cs.mu.OZ.AU (Fergus Henderson) (2002-08-14)
Exception Handling tschirre@cs.curtin.edu.au (Bernhard Tschirren) (1998-09-13)
Re: Exception Handling mrs@kithrup.com (1998-09-18)
Re: Exception Handling enikitin@apk.net (1998-09-18)
Re: Exception Handling landauer@apple.com (1998-09-18)
Re: Exception Handling mmc@oss.dk (Morten Christensen) (1998-09-26)
| List of all articles for this month |

From: "Fergus Henderson" <fjh@cs.mu.OZ.AU>
Newsgroups: comp.compilers
Date: 14 Aug 2002 02:20:41 -0400
Organization: Computer Science, University of Melbourne
References: 02-07-075 02-07-110 02-08-021
Keywords: errors, C
Posted-Date: 14 Aug 2002 02:20:41 EDT

"Nick Maclaren" <nmm1@cus.cam.ac.uk> writes:


>"Casse Hugues" <casse@netcourrier.com> writes:
>|> I uses the POSIX C functions setjmp()/lonjmp() from <setjmp.h> for
>|> emulating exceptions in my C programs. These functions stores the
>|> registers in a memory and restore it when the jump is performed. This is
>|> the faster way to implement it I know (in C).
>
>Unfortunately, that only appears to work. The C standard states
>explicitly that they will not work for real exception handling, though
>you can get them to work for language-created exceptions. Effectively
>that means that SYSTEM exceptions (e.g. SIGINT or even I/O errors)
>need system-specific code and Assembler.


This response is overly negative and as a result misleading.


Using setjmp()/longjmp() to implement exception handling works fine,
and is an entirely appropriate way to implement exceptions in a
compiler for a new language. In fact, this technique is used so often
that I am beginning to think that we should define a standard library
which encapsulates this technique -- not because it is difficult to
implement, but rather so that different language implementations which
use it can more easily interoperate.


You should not need to resort to using platform-dependent hacks to find
the return address in order to get proper clean-up handling; instead,
it would be sufficient to just make sure you establish a separate
handler for each different clean-up operation that you need.


Using setjmp()/longjmp() to implement exceptions should also be fine
for performance, so long as establishing signal handlers is rare.
If you have a language like C++ where you need clean-up code for
every object with a non-trivial destructor, then the performance
of setjmp()/longjmp() style exception handling won't be good.
But if you have a garbage-collected language, where explicit
resource management is rare, then the higher overhead to establish
an exception handler is quite acceptable, and indeed you probably
*don't* want to pay the space costs of the kind of table-based
implementation that is usually used for C++.


I/O can be coded using standard interfaces such as ISO C's fopen(),
fwrite(), etc. without any need for system-specific code or assembler.
I/O failures can be detected by checking the return value from these
functions, and handled by calling longjmp() to throw an exception if
they have failed.


Nick Maclaren is right to worry about using setjmp()/longjmp() exception
handling to deal with hardware exceptions or asynchronous signals.
Calling longjmp from signal handlers is indeed problematic. However,
this is no worse with the situation would be if you were compiling to
C++, because throwing C++ exceptions from signal handlers is even more
problematic.


The simplest way to deal with hardware exceptions such as division by
zero is to avoid them in the first place. For example, the C code that
you generate for division can first check to see if the operand is
zero, and if so, call longjmp() to throw an exception instead of
performing the division.


As for asynchronous signals, well, if you were thinking of treating
those as exceptions then you might want to rethink your language
design. There are some serious problems with such an approach.
The main one is that it becomes impossible to write exception-safe
code if exceptions can occur asynchronously.


--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.