为什么 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 ]

(强调我的)

See it live on Coliru.