在放松试验块期间,通过投掷破坏者而导致这种怪异的行为
What causes this weird behavior with throwing destructors during unwinding of a try-block?
本文关键字:破坏者 更新时间:2023-10-16
当try-block遇到异常时,堆栈就会解开。如果在try块内创建一个对象,则称为击曲线。如果破坏者抛出另一个例外,则不会捕获此例外,并且该程序被终止。
所以如果有:
struct A {
~A () noexcept(false) {
std::cout << "A::~A" << std::endl;
throw std::runtime_error("A::~A ERROR");
}
};
然后您的尝试键盘块类似于:
try {
A a1;
A a2;
} catch (...) {}
然后,当try块结束时, a2
的击离器抛出了异常,然后抓住了 a1
的驱动器,并且程序将终止。一切都按预期工作。
但是,如果您引入了另一个也会在灾难中抛出但从A
继承或以A
作为成员的实例的结构,那么事情就会令人困惑。例如,如果您有:
struct B : A {
~B () noexcept(false) {
std::cout << "B::~B" << std::endl;
throw std::runtime_error("B::~B ERROR");
}
};
,如果您这样做:
try {
B b;
A a;
} catch (...) {}
预期的结果应该是 A::~A
被称为例外,然后将B::~B
称为程序终止。但是,相反,在我尝试过除MSVC以外的所有编译器中,输出为:
A::~A
B::~B
A::~A
丢弃 std::runtime_error
what(): A::~A ERROR
好像被捕了两个例外,第三个例外终止了程序。
如果将B
定义为:
struct B {
~B () noexcept(false) {
std::cout << "B::~B" << std::endl;
throw std::runtime_error("B::~B ERROR");
}
A a;
};
我还尝试了其他一些结构的组合。
不要打扰将任何东西放在接管块中,因为该程序甚至永远不会去那里。
是的,我知道理想情况下甚至不应该抛出例外。阅读了有关投掷灾难的文章后,更多的好奇心。
我认为您要观察到的行为取决于实现。从std :: terminate((上的C 参考(强调我的(:
std :: terminate((在异常处理时由C 运行时调用 由于以下任何原因失败:
1(抛出一个例外 未捕获(它是实施定义的 在这种情况下完成(
在您的第一种情况下,退出范围:
- 调用了
A
的破坏者。 - 例外
std::runtime_error("A::~A ERROR")
被抛出。 -
catch(...)
捕获了这样的例外。 - 在放开堆栈时,也称为
B
的破坏者。 -
此时称为
std::terminate()
。但是实施定义是否a(该程序立即终止并给出您期望的输出
或
b(程序放弃堆栈,因此称为基类
A
的击路仪,然后终止;这就是您看到的观察。
请参阅Coliru上的代码
相关文章:
- 在放松试验块期间,通过投掷破坏者而导致这种怪异的行为
- 为什么我的虚拟破坏者多次执行这些执行
- 在销毁派生成员之前,在破坏者中调用共同功能
- 纯抽象类的虚拟破坏者
- 如何在CLION中的C 破坏者中达到断点
- 模拟一个函数,该函数像操作员=和破坏者一样传播到每个字段
- C :如何正确删除在类破坏者中的指针
- C 破坏者回收
- 模板基类的破坏者中的类型完整性不一致
- 使用std :: map时,包含unique_ptr的结构中的默认破坏者会导致编译错误
- 为什么我的破坏者只称呼一次,而不是在删除(a)调用上
- 与虚拟破坏者相比,Shared_PTR的运行时开销用于子类破坏
- 定义或声明类破坏者时,C 使用已删除的函数
- 在另一类中使用受保护的破坏者删除对象
- 永远循环的链接列表破坏者
- 不同版本的破坏者称为奇怪因素
- 将std :: lock_guard固定在破坏者中是安全的吗?
- 已经被破坏的一系列物体上的破坏者
- 即使在明确调用破坏者后,对象自动破坏也是如此
- 虚拟破坏者与普通破坏者