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: