问题
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;
}
}
回答1:
Your code is conforming and portable. But there be dragons here:
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.Since
exception_ptr
is copyable, and copies may point to the same exception object, andrethrow_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 acatch
clause. Modifications to that exception may produce a data race. That data race may exist on some platforms, and not on others, depending on whethercurrent_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).
UPDATE
Sorry, I have given an incorrect answer.
Using: http://webcompiler.cloudapp.net the output of the example code is:
0
0
The VS implementation of rethrow_exception
appears to make a copy of the exception.
Clang and gcc do not make copies.
来源:https://stackoverflow.com/questions/30580128/may-i-modify-the-value-of-an-exception-inside-a-stdexception-ptr