我可以在std :: exception_ptr中修改异常的值吗?

时间:2015-06-01 18:00:07

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

如果我在std::exception_ptr中存储了异常。我使用std::rethrow_exception重新抛出异常,使用catch(MyException&)访问它,然后修改该值。

如果我再次抛出相同的异常,我应该观察我做出的修改吗?

以下代码展示了我的想法:

#include <exception>
#include <iostream>

struct MyException {
    int value;
};

int main() {
    std::exception_ptr a = std::make_exception_ptr(MyException());

    try {
        std::rethrow_exception(a);
    } catch(MyException& b) {
        std::cout << b.value << std::endl;
        b.value = 3;
    }

    try {
        std::rethrow_exception(a);
    } catch(MyException& b) {
        std::cout << b.value << std::endl;
    }
}

1 个答案:

答案 0 :(得分:6)

您的代码符合并且可移植。但这里有龙:

  • 如果您通过exception_ptr获得current_exception(),则无法指定是否引用当前异常的副本或对当前异常本身的引用。即使您连续两次调用current_exception(),您也可能会或不会获得对同一异常对象的引用。

  • 由于exception_ptr是可复制的,并且副本可能指向同一个异常对象,并且rethrow_exception没有复制,因此很可能两个线程同时抛出相同的异常对象。因此,在多线程程序中,很难知道在catch子句中是否具有对异常的唯一访问权限。对该异常的修改可能会产生数据竞争。数据竞争可能存在于某些平台上,而不存在于其他平台上,具体取决于current_exception()是否复制。

因此,如果必须在多线程程序中修改异常对象,最先将其复制,修改副本,然后重新抛出副本(如有必要)。

<强>更新

抱歉,我给出了错误的答案。

使用:http://webcompiler.cloudapp.net示例代码的输出为:

0
0

rethrow_exception的VS实现似乎会复制该异常。

Clang和gcc不会复制。

相关问题