如果将它保存在std :: exception_ptr中,那么在catch语句之外使用异常是否安全?

时间:2015-05-26 15:32:54

标签: c++ exception c++11 exception-handling

我有一个std::exception_ptr,其中有一个例外。我将调用std::rethrow_exception来获取实际异常,异常在catch语句之后是否有效?我的猜测是,因为我仍然持有std::exception_ptr,它仍然有效。

参见示例:

std::exception_ptr ePtr = initialize_somewhere_else();
std::runtime_error* a=NULL;
try {
    std::rethrow_exception(ePtr);
} catch(std::runtime_error& e) {
    a = &e;
}
std::cout << a << ", " << a->what() << std::endl;

注意:在我使用Clang的测试中,这确实有效。

1 个答案:

答案 0 :(得分:3)

  

如果它在std :: exception_ptr中保存,那么在catch语句之外使用异常是否安全?

<德尔>是。您可以将exception_ptr视为指向异常的引用计数指针。只要exception_ptr引用它,该例外就会存在,而不再存在。

此外,rethrow_exception不会复制。

抱歉,我认为我的答案不正确。

这是检测测试:

#include <iostream>
#include <exception>
#include <stdexcept>


int
main()
{
    auto ePtr = std::make_exception_ptr(std::runtime_error("some text"));
    std::runtime_error* a = nullptr;
    try
    {
        std::rethrow_exception(ePtr);
    }
    catch(std::runtime_error& e)
    {
        a = &e;
    }
    *a = std::runtime_error("other text");
    try
    {
        std::rethrow_exception(ePtr);
    }
    catch(const std::runtime_error& e)
    {
        std::cout << e.what() << '\n';
    }
}

在gcc和clang上输出:

other text

这表示aePtr指的是完全相同的对象。

然而VS,根据http://webcompiler.cloudapp.net输出的当前版本:

some text

这表示aePtr引用了不同的对象。

现在的问题是VS是否符合这方面的要求。我的观点是,它并不重要。这是标准的一个有争议的领域,如果有争议,标准将被改变以符合现有的做法。

在我看来rethrow_exception在VS上制作副本,这意味着原始问题中e的生命周期不能保证与ePtr相关联。