如果我在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;
}
}
答案 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不会复制。