Boost logo

Boost :

From: Edd Dawson (lists_at_[hidden])
Date: 2007-09-15 08:44:30


Hi Howard,

Howard Hinnant wrote:

> class sticky_exception
> {
> bool owns_;
> sticky_exception& operator=(const sticky_exception&);
> public:
> sticky_exception() : owns_(true) {}
> sticky_exception(sticky_exception& s) : owns_(s.owns_) {s.owns_ =
> false;}
> // sticky_exception(sticky_exception&& s) : owns_(s.owns_) {s.owns_
> = false;}
> ~sticky_exception() {if (owns_) {sticky_exception s; throw s;}}
> };

Does this destructor not invoke some kind of recursive nuttiness that leads to
std::terminate()?

If a sticky_exception is created on "the stack", any throw statements made
thereafter in the same scope will invoke the destructor of that
sticky_exception, at which point we end up doing this (calling
~sticky_exception) all over again.

I though 15.5.1 would apply, here?

"In the following situations exception handling must be abandoned for less
subtle error handling techniques:
[...]
-- when the destruction of an object during stack unwinding (15.2) exits using
an exception
[...]
In such cases,
     void terminate();
is called (18.6.3)."

For example, the following program prints "genesis!" and "terminating!", but not
"death!" (at least with MSVC8, gcc 3.4.5, gcc 4.2.1 and DMC 8.42n. Borland bcc32
5.82 disagrees):

#include <exception>
#include <iostream>

class sticky_exception
{
      bool owns_;
      sticky_exception& operator=(const sticky_exception&);
public:
      sticky_exception() : owns_(true) {}
      sticky_exception(sticky_exception& s) : owns_(s.owns_) {s.owns_ = false;}
      ~sticky_exception() {if (owns_) {sticky_exception s; throw s;}}
};

struct noisy
{
     noisy() { std::cerr << "genesis!\n"; }
     ~noisy() { std::cerr << "death!\n"; }
};

void handler()
{
     std::cerr << "terminating!\n";
}

int main()
{
     std::set_terminate(handler);

     {
         noisy n;
         sticky_exception s;
         throw s;
     }
     return 0;
}

So how is creating a sticky_exception any different to a glorified call to
std::terminate() (at the end of scope)? Or am I missing something crazy-obvious?

Cheers,

Edd


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk