[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#516862: optimization can prevent terminate() from being called on throw from destructor while unwinding



Package: g++-4.3
Version: 4.3.2-1.1 , 4.3.3-4

This is also in at least g++-4.1 (4.1.2-25 and 4.1.1-21) and g++-4.2
(4.2.4-6). I don't have a g++-3.x installed to test with.

This is on i386.


The program at the end of this report should always print
"my_terminate()" and exit. If the "WTF dont_call_terminate;" line is
commented, that's what it does. If -O0 is given, that's what it does.

If that line is not commented and -O2, -O1, or -Os is given, it breaks
differently depending on whether the "inline" is commented.

With the "inline" commented, both throw_twice_no_terminate() and
throw_twice() result in "caught a 'std::exception'". With the inline
uncommented, throw_twice_no_terminate() results in "inner handler",
while throw_twice() results in "my_terminate()".



#include <iostream>
#include <stdexcept>
#include <cstdlib>

void my_terminate() {
  std::cerr<<"my_terminate()\n";
  exit(1);
}

class WTF {
public:
  ~WTF(){}
};

class throwing_dtor
{
  WTF dont_call_terminate;
public:
  throwing_dtor() {}
  ~throwing_dtor()
  {
    throw std::exception();
  }
};

inline // it breaks differently if this is commented
void do_throw_twice() {
  throwing_dtor td;
  throw std::exception();
}

void throw_twice() {
  try {
    do_throw_twice();
  } catch (std::exception & e) {
    std::cerr<<"caught a '"<<e.what()<<"'\n";
  } catch (...) {
    std::cerr<<"inner handler\n";
  }
}

void throw_twice_no_terminate() {
  try {
    throw_twice();
  } catch (...) {
    std::cerr<<"outer handler\n";
  }
}

int main() {
  std::set_terminate(&my_terminate);

  throw_twice_no_terminate();
  std::cerr<<"now without the outer catch...\n";
  throw_twice();

  return 0;
}





Reply to: