我可以修改 std::exception_ptr 中的异常值吗?
May I modify the value of an exception inside a std::exception_ptr?
如果我在 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;
}
}
您的代码符合标准且可移植。但是这里有龙:
如果您通过 current_exception()
获取您的 exception_ptr
,则不确定您是获取对当前异常的副本的引用,还是对当前异常本身的引用.即使您连续两次调用 current_exception()
,您也可能会或可能不会获得对同一异常对象的引用。
由于exception_ptr
是可复制的,而副本可能指向同一个异常对象,而rethrow_exception
不会复制,两个线程很可能同时抛出同一个异常对象。所以在多线程程序中,很难知道您是否对 catch
子句中的异常具有唯一访问权限。对该异常的修改可能会产生数据竞争。数据竞争可能存在于某些平台上,而不存在于其他平台上,这取决于 current_exception()
是否进行复制。
所以如果在多线程程序中一定要修改一个异常对象,最保险的做法是先拷贝,修改拷贝,然后再抛出拷贝(必要时)。
更新
对不起,我的回答有误。
使用:http://webcompiler.cloudapp.net示例代码的输出是:
0
0
rethrow_exception
的 VS 实现似乎复制了异常。
Clang 和 gcc 不复制。
如果我在 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;
}
}
您的代码符合标准且可移植。但是这里有龙:
如果您通过
current_exception()
获取您的exception_ptr
,则不确定您是获取对当前异常的副本的引用,还是对当前异常本身的引用.即使您连续两次调用current_exception()
,您也可能会或可能不会获得对同一异常对象的引用。由于
exception_ptr
是可复制的,而副本可能指向同一个异常对象,而rethrow_exception
不会复制,两个线程很可能同时抛出同一个异常对象。所以在多线程程序中,很难知道您是否对catch
子句中的异常具有唯一访问权限。对该异常的修改可能会产生数据竞争。数据竞争可能存在于某些平台上,而不存在于其他平台上,这取决于current_exception()
是否进行复制。
所以如果在多线程程序中一定要修改一个异常对象,最保险的做法是先拷贝,修改拷贝,然后再抛出拷贝(必要时)。
更新
对不起,我的回答有误。
使用:http://webcompiler.cloudapp.net示例代码的输出是:
0
0
rethrow_exception
的 VS 实现似乎复制了异常。
Clang 和 gcc 不复制。