我可以在std :: exception_ptr中修改异常的值吗? [英] May I modify the value of an exception inside a std::exception_ptr?
问题描述
如果我在 std :: exception_ptr
中存储了一个异常。我使用 std :: rethrow_exception
重新抛出异常,使用 catch(MyException&)
访问它,然后我修改值
If I have a exception stored inside std::exception_ptr
. I rethrow the exception using std::rethrow_exception
, access it using catch(MyException&)
and then I modify the value.
如果我再次抛出相同的异常,我应该遵守我所做的修改吗?
If I throw the same exception again, should I observe the modification I made?
以下代码演示我的想法:
The following code demonstrate my idea:
#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;
}
}
推荐答案
你的代码是一致的和便携的。但是这里有龙:
Your code is conforming and portable. But there be dragons here:
-
如果你获得了
exception_ptr
viacurrent_exception()
,无论您是否引用当前异常的副本,还是引用当前的异常本身。即使您连续两次调用current_exception()
,也可能不会引用同一个异常对象。
If you obtain your
exception_ptr
viacurrent_exception()
, it is unspecified whether you get a reference to a copy of the current exception, or a reference to the current exception itself. Even if you callcurrent_exception()
twice in a row, you may or may not get a reference to the same exception object.
由于 exception_ptr
是可复制的,并且副本可能指向相同的异常对象,而 rethrow_exception
不做一个副本,两个线程很可能同时抛出同一个异常对象。所以在一个多线程程序中,很难知道你是否有独特的访问 catch
子句中的异常。修改该异常可能会产生数据竞赛。数据竞赛可能存在于某些平台上,而不在其他平台上,具体取决于 current_exception()
是否复制。
Since exception_ptr
is copyable, and copies may point to the same exception object, and rethrow_exception
doesn't make a copy, it is quite possible for two threads to throw the same exception object simultaneously. So in a multi-threaded program, it can be very difficult to know if you have unique access to an exception within a catch
clause. Modifications to that exception may produce a data race. That data race may exist on some platforms, and not on others, depending on whether current_exception()
makes a copy or not.
所以如果你必须修改多线程程序中的一个异常对象,最安全的是先复制它,修改副本,然后重新抛出副本(如果
So if you must modify an exception object in a multi-threaded program, it is safest to copy it first, modify the copy, and then rethrow the copy (if necessary).
更新
对不起,我给了一个不正确的答案。
Sorry, I have given an incorrect answer.
使用: http://webcompiler.cloudapp.net 示例代码的输出是:
Using: http://webcompiler.cloudapp.net the output of the example code is:
0
0
rethrow_exception
的VS实现似乎会创建异常的副本。
The VS implementation of rethrow_exception
appears to make a copy of the exception.
Clang和gcc不复制。
Clang and gcc do not make copies.
这篇关于我可以在std :: exception_ptr中修改异常的值吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!