[gnu.g++] Unwinding vs destructors

nagle@well.UUCP (John Nagle) (08/15/89)

    C++ destructors provide a means to force cleanup of an object as it
disappears upon exit from a scope.  Unfortunately, the "longjmp" mechanism
evades destructor processing.  "longjmp" is an old hack, only sort of part
of C.  But it is useful.  Should C++ have a better escape mechanism,
along the lines of "throw" and "return-from" in Common LISP or "raise" in
Ada?  With those mechanisms, appropriate cleanup processing is performed
as the scopes unwind.  But C++ lacks such a mechanism.

     One could argue that such mechanisms violate the "no hidden machinery"
concept of C.  But C++ already has destructors, functions which are invoked
by the language system, not explicitly by the user.  What do people think?

					John Nagle

ttwang@polyslo.CalPoly.EDU (Thomas Wang) (08/17/89)

nagle@well.UUCP (John Nagle) writes:

>    C++ destructors provide a means to force cleanup of an object as it
>disappears upon exit from a scope.  Unfortunately, the "longjmp" mechanism
>evades destructor processing.  "longjmp" is an old hack, only sort of part
>of C.  But it is useful.  Should C++ have a better escape mechanism,
>along the lines of "throw" and "return-from" in Common LISP or "raise" in
>Ada?  With those mechanisms, appropriate cleanup processing is performed
>as the scopes unwind.  But C++ lacks such a mechanism.

I would suggest something like the following:

extern int error_code, error_type;

real square_root(real val)
{
  real result;
  pre_condition : val > 0.0;
  post_condition: (result * result + .1 > val) && (result * result - .1 < val);

  char* tempbuf = (char*) malloc(80 * sizeof(char));
  if (tempbuf == 0)
  {
    error_code = 1;
    fail; // goto the recovery handler.  If no recovery handler exists,
          // pop stack & propogate failure upwards.
  }
  calculation_follows();
  return result;
recovery:
  switch (error_type)
  {
  case 0: // pre-condition failed
    if (val > 0.0)
    {
       val = - val;
       retry; // retry will pop all local variables, and goto top of function
    }
    break; // if we falls through, failure will propogate upward toward
           // main() function
  case 1: // post-condition failed
    cout << "incorrect result was generated.\n";
    break;
  case 2: // class-invarient failed
    break;
  case 3: // raised by the 'fail' statement
    if (error_code == 1)
      cout << "out of memory\n";
    break;
  case 4: // previous failure propogated to here
    break;
  }
}

>     One could argue that such mechanisms violate the "no hidden machinery"
>concept of C.  But C++ already has destructors, functions which are invoked
>by the language system, not explicitly by the user.  What do people think?

I think this error handling mechanism is fairly explicit, and replaces all
instances of ad-hoc error checkings.  The mechanism is borrowed from
Eiffel if you have not noticed already.

>					John Nagle

 -Thomas Wang ("This is a fantastic comedy that Ataru and his wife Lum, an
                invader from space, cause excitement involving their neighbors."
                  - from a badly translated Urusei Yatsura poster)

                                                     ttwang@polyslo.calpoly.edu

ted@nmsu.edu (Ted Dunning) (08/23/89)

In article <13635@polyslo.CalPoly.EDU> ttwang@polyslo.CalPoly.EDU (Thomas Wang) writes:


   nagle@well.UUCP (John Nagle) writes:

   >    C++ destructors provide a means to force cleanup of an object as it
   >disappears upon exit from a scope.  Unfortunately, the "longjmp" mechanism
   >evades destructor processing.  "longjmp" is an old hack, only sort of part
   >of C.  But it is useful.  Should C++ have a better escape mechanism,
   >along the lines of "throw" and "return-from" in Common LISP or "raise" in
   >Ada?  With those mechanisms, appropriate cleanup processing is performed
   >as the scopes unwind.  But C++ lacks such a mechanism.

   I would suggest something like the following:

   extern int error_code, error_type;
	... sample code ...

   I think this error handling mechanism is fairly explicit, and replaces all
   instances of ad-hoc error checkings.  The mechanism is borrowed from
   Eiffel if you have not noticed already.

i didn't actually notice.

i have implemented a unwind_protect/catch/throw mechanism for
unadorned c that would be easy to move to c++.  this mechanism is
based on the semantics of these constructs in common lisp and should
provide a robust non-local return mechanism if longjmp is not used.
it is probably desirable that an error/debug mechanism be implemented
alongside the catch/throw mechanism based on the experience in common
lisp.

if anyone is interested, i can either post/email the code (it is
really pretty small).

--
ted@nmsu.edu
			Most of all, he loved the fall
			when the cottonwoods leaves turned gold
			and floated down the trout streams
			under the clear blue windswept skies.