OznOg
OznOg

Reputation: 4722

why is std::terminate not called when throwing in my destructor

I'm trying to "see" the call to std::terminate() when throwing from a destructor with the following code:

#include <stdexcept>

struct boom {
     ~boom() {
        throw std::logic_error("something went wrong");
     }
};

int main() {
     boom();
}

compiled with g++ and run the code:

# ./a.out
terminate called after throwing an instance of 'std::logic_error'
  what():  something went wrong
Aborted (core dumped)

so far so good, seems to work as expected (call terminate()). But when trying to break on terminate in gdb, the function does not get hit and the backtrace shows only abort:

(gdb) b std::terminate
Breakpoint 2 at 0x7f60a3772240 (2 locations)
(gdb) r
Starting program: a.out
terminate called after throwing an instance of 'std::logic_error'
  what():  something went wrong

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f2c241eb921 in __GI_abort () at abort.c:79
#2  0x00007f2c24628957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007f2c2462eae6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007f2c2462db49 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007f2c2462e4b8 in __gxx_personality_v0 () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007f2c23c05573 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#7  0x00007f2c23c05ad1 in _Unwind_RaiseException () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#8  0x00007f2c2462ed47 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x0000558cee09593a in boom::~boom() ()
#10 0x0000558cee0958dd in main ()
(gdb)

This behavior is puzzling me somehow, is there something I am missing?

EDIT:

same test using clang++ and the std::terminate breakpoint is hit:

Breakpoint 1, 0x0000000000400750 in std::terminate()@plt ()
(gdb) bt
#0  0x0000000000400750 in std::terminate()@plt ()
#1  0x00000000004009bf in __clang_call_terminate ()
#2  0x000000000187eef0 in ?? ()
#3  0x00000000004009a4 in boom::~boom() ()
#4  0x00000000004008f1 in main ()
(gdb)

Upvotes: 2

Views: 755

Answers (1)

user4442671
user4442671

Reputation:

You are running into the as-if rule.

C++ compilers are allowed to essentially rewrite your entire program as they see fit as long as the side effects remain the same.

What a side effect is very well defined, and "a certain function gets called" is not part of that. So the compiler is perfectly allowed to just call abort() directly if it can determine that this is the only side effect std::terminate() would have on the program.

You can get more details at https://en.cppreference.com/w/cpp/language/as_if

Upvotes: 2

Related Questions