当我们从析构函数中throw
时会发生什么?我知道它会导致terminate()
被调用,内存确实被释放并且析构函数被调用,但是, throw
之前或之后的是从{{1 }}?也许这里的问题是在堆栈放松时使用foo
是问题所在。
答案 0 :(得分:13)
是从foo调用throw之前还是之后?
这就是发生的事情:
foo()
被称为a
的对象A
a
的dtor,它会抛出另一个异常std::terminate
- 这只是放弃了异常处理机制:来自C ++ 0x草案:
15.5.1 std :: terminate()函数
1 在以下情况下例外 必须放弃处理 微妙的错误处理技术:
[...] - 破坏的时候 堆栈展开期间的对象 (15.2)使用例外退出,或
2 在这种情况下,std :: terminate()是 叫(18.7.3)。在这种情况下 它没有找到匹配的处理程序 是实现定义是否或 堆栈之前没有解开 调用std :: terminate()。 总而言之 在其他情况下,堆栈不得 在std :: terminate()之前解开 调用。实现不是 允许完成堆栈展开 过早地基于决心 放松过程会 最终打电话给 的std ::终止()。
注意:强调我的
答案 1 :(得分:2)
以下是g ++中发生的事情:
#include <stdio.h>
class A {
public:
~A()
{
fprintf(stderr, "in ~A\n");
throw "error";
}
};
void foo()
{
A a;
fprintf(stderr, "in foo\n");
throw "error";
}
int main()
{
try {
foo();
}
catch (const char*) {
return 1;
}
return 0;
}
[~/ecc/ellcc/ecc] main% ./a.out
in foo
in ~A
terminate called after throwing an instance of 'char const*'
Abort
[~/ecc/ellcc/ecc] main%
正如你所看到的,抛出foo首先发生,然后抛入~A会导致错误。
答案 2 :(得分:1)
如果我没有弄错的话,一旦调用terminate
,就不会发生(进一步)堆栈展开。
terminate
调用处理函数(可以使用set_terminate
设置):
要处理的函数的类型 终止时由terminate()调用 异常处理。
<强>必需 行为强>: terminate_handler应终止程序的执行 没有回到来电者 默认行为: 实现的默认terminate_handler调用abort()。
至少我不知道如何“终止执行而不返回调用者”,这将允许你解除堆栈。
您可以修改示例以查看您可以期待的内容:
#include <cstdio>
class A
{
public:
~A() {
puts("Entered A destructor");
throw "error";
}
};
void foo()
{
A a, b;
throw "error";
}
int main()
{
try {
foo();
} catch (const char*) {
return 1;
}
}
现在有两个A实例,并且永远不会调用第二个实例的析构函数,因为只要第一个A的析构函数完成并且让另一个异常转义就会终止执行。
答案 3 :(得分:1)
你有点错误,这就是你不明白的原因。你看,抛出析构函数不会导致teriminate()
函数被调用,这是一个不好的做法,但它对程序执行并不致命。什么是致命的是一些代码在仍有活动异常的情况下抛出。 C ++无法决定进一步传播哪个异常,新的或旧的异常,并且它们都不能传播它们。程序执行被认为是致命的,这就是调用终止的原因。
所以,你看,如果没有抛出foo
,将不会调用terminate,但会从~A
抛出异常。所以,当然,必须首先调用foo,然后在第二次投掷期间,所有内容都会中断。
答案 4 :(得分:0)
对象a
是一个堆栈对象,因此没有动态内存可供释放。一旦控制超出foo()
的范围,堆栈框架以及对象就不再存在。
答案 5 :(得分:0)
为了说明,这是Microsoft C ++中发生的事情:
#include <iostream>
class A {
public:
~A() {
std::cout << "in ~A" << std::endl;
throw "error";
}
};
void foo() {
A a;
std::cout << "in foo" << std::endl;
throw "error";
}
int main() {
try {
foo();
}
catch (void *) {
std::cout << "exit: 1" << std::endl;
return 1;
}
std::cout << "exit: 0" << std::endl;
return 0;
}
结果:
>cpptest1.exe
in foo
in ~A
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
>