为什么在抛出我的析构函数时没有调用 std::terminate

氧化锌

当使用以下代码从析构函数抛出时,我试图“看到”对 std::terminate() 的调用:

#include <stdexcept>

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

int main() {
     boom();
}

用 g++ 编译并运行代码:

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

到目前为止一切顺利,似乎按预期工作(调用终止())。但是当尝试在 gdb 中终止时,该函数不会被击中,并且回溯仅显示中止:

(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)

这种行为以某种方式让我感到困惑,我是否缺少某些东西?

编辑:

使用 clang++ 进行相同的测试,并且命中了 std::terminate 断点:

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)
坦率

您遇到了 as-if 规则。

只要副作用保持不变,C++ 编译器就可以按照他们认为合适的方式重写整个程序。

什么副作用是非常明确的,“某个函数被调用”不是其中的一部分。因此,如果编译器abort()可以确定这是std::terminate()对程序产生的唯一副作用,则完全允许编译器直接调用

您可以在https://en.cppreference.com/w/cpp/language/as_if获取更多详细信息

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我可以直接调用 std::terminate 吗?

当抛出前一个异常时从(创建/复制/移动)构造函数中抛出异常时,为什么不调用 std::terminate()?

为什么调用shared_from_this会调用std :: terminate

当对象绑定到成员函数时,为什么std :: function会调用析构函数?

为什么std :: shared_ptr两次调用我的析构函数?

防止线程在处理异常后在分离时调用std :: terminate()

为什么C ++不使用std :: nested_exception允许从析构函数中抛出?

为什么std :: vector的构造函数调用自定义类的析构函数?

为什么std :: vector在离开其他作用域的同时调用析构函数?

什么时候调用std :: thread析构函数?

为什么从`std :: async`阻塞返回的是将来的析构函数?

从noexcept函数参数的构造函数引发的异常是否会立即导致对std :: terminate()的调用?

throw()函数是否应始终在异常上展开堆栈并允许捕获异常或必须调用std :: terminate?

可见性受限的`noexcept`函数中的`std :: terminate`调用-GCC vs Clang Codegen

std::map 对象析构函数被调用?

从类成员初始化程序引发的异常应该调用std :: terminate()吗?

为什么要在std :: vector :: push_back(T object)方法中构造对象时调用析构函数?

DLL的std :: set_terminate吗?

std::terminate() 是否触发堆栈展开?

std :: vector中的元素可能具有抛出的析构函数吗?

在某些情况下,使用std :: set_terminate无法捕获C ++纯虚函数调用吗?

std :: list的擦除成员函数是否为所有存储的元素调用析构函数?

为什么`std :: exit`不能按预期触发析构函数?

为什么std :: unary_function不包含虚拟析构函数

为什么C ++标准为std :: bitset :: reference指定析构函数?

为什么使用虚拟析构函数进行std :: vector :: push_back segfaults?

无法手动调用std :: string的析构函数

std :: remove_if是否调用析构函数?

std :: move意外调用析构函数