Topic: is this a ill-formed program?


Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/08/10
Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.crud.com> wrote:

> It shouldn't be, but it looks like exactly the sort of obscure thing
> some compilers might screw up. Personally, I think the value of
> uncaught_exception should be saved and cleared on entry to a try block
> (such as the one inside destroy::~destroy), and restored on completion
> of the try block (either in-line or via exception). In other words, I
> think uncaught_exception should mean that you mustn't throw an
> exception. As I understand the latest draft, though, it should return
> true even inside the try block, where it is perfectly safe to throw an
> exception.

It may have been safe in the particular example that was being
discussed, but in general it is _not_ safe to throw an exception if
another exception has been thrown and not yet handled, even inside a
try block.  There are two reasons for this.  Firstly, the try block
might not catch your exception.  Secondly, the try block may rethrow
your exception without checking uncaught_exception().  For example the
try block may be

 int *p = new Foo[n];
 try {
  ...
 }
 catch(...) {
  delete [] p;
  throw;
 }

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: wyrmok@plg.uwaterloo.ca (Russell Mok)
Date: 1997/08/04
Raw View
#include<stdio.h>

void throwInt() { throw 0; }

void throwChar() { throw 'c'; }

struct destroy {
  destroy() {}
  ~destroy() {
    try {
      printf("destructor\n");
      throwInt();
    }
    catch (int &) {
      printf("destroy catch int\n");
      // throw;
    }
  }
};


void main () {
  printf("main1\n");

  try {
    destroy abc;
    throwChar();

  }
  catch (int &x) {
    printf("caught int\n");
  }
  catch (char &c) {
    printf("caught char\n");
  }
  catch (...) {
    printf("caught sth\n");
  }

  printf("end\n");
}

I compile the above program with g++2.7.2.1 without optimization on a
sun-sparc.  The output is the following:

main1
destructor
destroy catch int
caught int
end


I expect the main program to catch a char intead of an int.

If I uncommented the re-throw inside the destructor handler, the
program does a core dump and the function teminate() is invoked.  I
know throwing an exception in a destructor is not recommanded, but I
don't think it is prohibited.  Of course, I don't know what the
lattest draft says about that.

Btw, does anyone know how the uncaught_exception() should work if I
throw another exception (inside a destructor, or a function called by
a destructor) if uncaught_exception() is already true, i.e., is it set
to false if the 2nd exception is caught?

Russell

--
Russell Mok
Dept of Computer Science, University of Waterloo
Waterloo, Ontario, Canada  N2L 3G1
email: wyrmok@plg.uwaterloo.ca
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: bill@gibbons.org (Bill Gibbons)
Date: 1997/08/07
Raw View
In article <33E6D417.5266@ix.netcom.crud.com>, "Paul D. DeRocco"
<pderocco@ix.netcom.crud.com> wrote:

> > Btw, does anyone know how the uncaught_exception() should work if I
> > throw another exception (inside a destructor, or a function called by
> > a destructor) if uncaught_exception() is already true, i.e., is it set
> > to false if the 2nd exception is caught?
>
> It shouldn't be, but it looks like exactly the sort of obscure thing
> some compilers might screw up. Personally, I think the value of
> uncaught_exception should be saved and cleared on entry to a try block
> (such as the one inside destroy::~destroy), and restored on completion
> of the try block (either in-line or via exception). In other words, I
> think uncaught_exception should mean that you mustn't throw an
> exception. As I understand the latest draft, though, it should return
> true even inside the try block, where it is perfectly safe to throw an
> exception. To adhere to those semantics, it would have to maintain a
> count of pending exceptions, and return true as long as the count is
> nonzero. But I think that's less useful.

There are many things that would be useful to know about pending
exceptions.  WG21/J16 decided not to try to cover everything, but to
answer this critical question using uncaught_exception():

   If an exception is thrown right now, and is neither caught
   nor found to violate an exception-specification, and no
   subsequent exceptions are thrown, will the program exit via
   terminate() [as opposed to unexpected()]?

This was thought to be the single most useful thing to know when
trying to avoid calls to terminate().  Of course not everyone agrees.

-- Bill Gibbons
   bill@gibbons.org
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Steve Clamage <stephen.clamage@eng.sun.com>
Date: 1997/08/08
Raw View
Russell Mok wrote:
>
> #include<stdio.h>
>
> void throwInt() { throw 0; }
>
> void throwChar() { throw 'c'; }
>
> struct destroy {
>   destroy() {}
>   ~destroy() {
>     try {
>       printf("destructor\n");
>       throwInt();
>     }
>     catch (int &) {
>       printf("destroy catch int\n");
>       // throw;
>     }
>   }
> };
>
> void main () {
>   printf("main1\n");
>
>   try {
>     destroy abc;
>     throwChar();
>
>   }
>   catch (int &x) {
>     printf("caught int\n");
>   }
>   catch (char &c) {
>     printf("caught char\n");
>   }
>   catch (...) {
>     printf("caught sth\n");
>   }
>
>   printf("end\n");
> }

Well, "void main" does not conform to the draft standard, but that
probably isn't what you mean.

> I compile the above program with g++2.7.2.1 without optimization on a
> sun-sparc.  The output is the following:
>
> main1
> destructor
> destroy catch int
> caught int
> end
>
> I expect the main program to catch a char intead of an int.

Yes, it should. Either gcc is promoting the thrown char to
an int before actually throwing it, or it creates a temporary
int out of the char rvalue and allows it to be matched to the
int&. Neither one of those things is correct.

> If I uncommented the re-throw inside the destructor handler, the
> program does a core dump and the function teminate() is invoked.  I
> know throwing an exception in a destructor is not recommanded, but I
> don't think it is prohibited.

It is not prohibited, but in this case is supposed to cause
your program to exit via a call to terminate(). That might in
turn cause a core dump.

The throwChar function exits via an exception, which causes
the abc object to be destroyed before the exception can be
handled. The destructor for abc now exits via an exception
before the previous exception is handled. That circumstance
requires that terminate be called. (It is OK to throw and
catch an exception within the same function while another
exception is being handled, but not to exit a function
via an exception while another exception is being handled.)

> Btw, does anyone know how the uncaught_exception() should work if I
> throw another exception (inside a destructor, or a function called by
> a destructor) if uncaught_exception() is already true, i.e., is it set
> to false if the 2nd exception is caught?