【问题标题】:May I modify the value of an exception inside a std::exception_ptr?我可以修改 std::exception_ptr 内的异常值吗?
【发布时间】:2015-06-02 23:26:47
【问题描述】:

如果我有一个异常存储在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;
    }
}

【问题讨论】:

  • 观察修改是什么意思?
  • @perencia 如果我重新抛出相同的异常,它会有我所做的修改。在我的代码示例中,我第二次抛出 a 我在 value 中有 3 个。
  • 在示例中,您始终使用同一个对象,通过引用来捕获它。
  • 他根本没有证明这一点。
  • 证明是一个强有力的词。仅仅因为它适用于我的编译器和我的平台并不意味着它根据 C++ 标准是正确的。

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


【解决方案1】:

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

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

  • 1234563同一个异常对象同时进行。因此,在多线程程序中,很难知道您是否对catch 子句中的异常具有唯一访问权限。对该异常的修改可能会产生数据竞争。这种数据竞争可能存在于某些平台上,而不存在于其他平台上,这取决于 current_exception() 是否复制。

所以如果一定要在多线程程序中修改异常对象,最安全的做法是先拷贝,修改拷贝,然后重新抛出拷贝(如果需要的话)。

更新

对不起,我的答案不正确。

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

0
0

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

Clang 和 gcc 不会复制。

【讨论】:

  • 所以在重新抛出异常时不能有副本?
  • @Yakk:这就是我阅读 [propagation]/p10 的方式:抛出:p 所指的异常对象。相反地​​,p8 在描述current_exception() 时不遗余力地描述了未指定的复制语义。
  • 根据你的回答,我能推断出stackoverflow.com/questions/30462906/…“是的。它是安全的”的答案吗?
猜你喜欢
  • 2017-10-03
  • 2017-05-08
  • 2016-12-17
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多