为什么 unique_ptr 析构函数的异常会终止程序?
Why exceptions from unique_ptr destructor terminates the program?
看看这段代码,它导致程序在未捕获异常的情况下终止。
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>
using namespace std;
struct test {
~test() noexcept(false) {
throw runtime_error("-my-cool-exception-");
}
};
int main()
{
try {
auto ptr = unique_ptr<test>(new test());
//test t; // this is ok, without unique_ptr<test> it works fine.
}
catch(exception& e) {
cout << "this is not called, the program is aborted";
cout << e.what() << endl;
}
return 0;
}
这道题不同于栈溢出题:throwing exceptions out of destructor.
不同的是只有当我使用unique_ptr<test>
时才不会捕获异常。
您可以在此处查看实时代码、编辑和编译http://cpp.sh/9sk5m
这是标准要求的。根据 unique.ptr.single.dtor, 20.10.1.2.2.1:
Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. [ Note: The use of default_delete requires T to be a complete type. — end note ]
(强调我的)
所以真的,你的析构函数本身是否有 noexcept(false)
并不重要。在这种情况下禁止抛出 - 最终决定。
这是一般情况下的情况std::
——除非另有说明。根据 res.on.functions, 17.6.4.8.2.4:
In particular, the effects are undefined in the following cases:
[...]
if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
(强调我的)
注意:一般来说,您 可以 使用 noexcept(false)
抛出析构函数。然而,这是非常危险的,因为如果堆栈由于抛出的异常 而展开,则会调用 std::terminate
。
根据 except.ctor, 15.2.1:
As control passes from the point where an exception is thrown to a handler, destructors are invoked by a process, specified in this section, called stack unwinding. If a destructor directly invoked by stack unwinding exits with an exception, std::terminate is called ([except.terminate]). [ Note: Consequently, destructors should generally catch exceptions and not let them propagate out of the destructor. — end note ]
(强调我的)
看看这段代码,它导致程序在未捕获异常的情况下终止。
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>
using namespace std;
struct test {
~test() noexcept(false) {
throw runtime_error("-my-cool-exception-");
}
};
int main()
{
try {
auto ptr = unique_ptr<test>(new test());
//test t; // this is ok, without unique_ptr<test> it works fine.
}
catch(exception& e) {
cout << "this is not called, the program is aborted";
cout << e.what() << endl;
}
return 0;
}
这道题不同于栈溢出题:throwing exceptions out of destructor.
不同的是只有当我使用unique_ptr<test>
时才不会捕获异常。
您可以在此处查看实时代码、编辑和编译http://cpp.sh/9sk5m
这是标准要求的。根据 unique.ptr.single.dtor, 20.10.1.2.2.1:
Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. [ Note: The use of default_delete requires T to be a complete type. — end note ]
(强调我的)
所以真的,你的析构函数本身是否有 noexcept(false)
并不重要。在这种情况下禁止抛出 - 最终决定。
这是一般情况下的情况std::
——除非另有说明。根据 res.on.functions, 17.6.4.8.2.4:
In particular, the effects are undefined in the following cases: [...] if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
(强调我的)
注意:一般来说,您 可以 使用 noexcept(false)
抛出析构函数。然而,这是非常危险的,因为如果堆栈由于抛出的异常 而展开,则会调用 std::terminate
。
根据 except.ctor, 15.2.1:
As control passes from the point where an exception is thrown to a handler, destructors are invoked by a process, specified in this section, called stack unwinding. If a destructor directly invoked by stack unwinding exits with an exception, std::terminate is called ([except.terminate]). [ Note: Consequently, destructors should generally catch exceptions and not let them propagate out of the destructor. — end note ]
(强调我的)