In C++, if a local variable's destructor throws after the return value object has been created, the return value object is never destroyed! G++ uses the allowed C++ return value optimisation and creates a return value object directly without copying it. This is probably one source of the bug.
This bug manifests in all versions of g++ (3.2.3 - 4.2.2) I happened to have on my machine, it also shows on both i686 and x86_64 architectures. It seems that throwing destructors are rare enough so that this bug has gone unnoticed for really long... :) Test case: -------- etest.cc -------------- #include <iostream> #include <ostream> using namespace std; class X { public: X(bool throws) : throws_(throws) { cerr << "X::X() (" << throws_ << ")" << endl; } X(const X& x) : throws_(x.throws_) { cerr << "X::X(const X&) (" << throws_ << ")" << endl; } ~X() { cerr << "X::~X() (" << throws_ << ")" << endl; if (throws_) { throw 1; } } private: bool throws_; }; X f() { X x(true); return X(false); } int main() { try { f(); } catch (...) { cerr << "Catch!" << endl; } } ---------- end of etest.cc ----------- pulu:/home/bitti/tmp/t> g++ etest.cc pulu:/home/bitti/tmp/t> ./a.out X::X() (1) X::X() (0) X::~X() (1) Catch! -- Summary: Return value's destructor not executed when a local variable's destructor throws Product: gcc Version: 4.2.1 Status: UNCONFIRMED Severity: major Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: bitti at iki dot fi GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33799