【问题标题】:Crash in std::promise::set_value crashstd::promise::set_value 崩溃中的崩溃
【发布时间】:2021-05-14 09:29:08
【问题描述】:

错误: 在抛出 'std::future_error' 的实例后调用终止 what(): std::future_error: 无关联状态

g++ --version 7.5.0 但是,相同的代码行在具有相同 g++ 版本的 QNX 上运行良好。

另外,如果我们生成一个新线程并将 promise 作为参数移动到该线程函数,那么当在 promise 对象上调用 set_value() 时,异常不是属于自己的。

我的确切问题是,如果这是预期的行为, 有没有办法转移承诺对象的所有权,以便其他线程可以在稍后执行期间使用它。 除了产生一个新线程,而是能够从一个已经存在的线程访问 Promise。

#include <future>

using namespace std;

int main()
{
    promise<int> p1;
    promise<int> p2(move(p1));
    p1.set_value(99); // SIGSEGV!
}

【问题讨论】:

  • 等一下...您已将p1 移动到p2,然后将状态设置为p1?那应该怎么做?
  • 这里没有崩溃。抛出了一个异常。 std::terminate 被调用。显示了描述问题的消息。 您的问题究竟是什么?你问它为什么会抛出?为什么调用终止?如何在不投掷的情况下完成您的预期任务?
  • 我相信throw/terminate 是正确的行为。你从来没有为承诺创造过未来,那么set_value到底应该做什么?
  • @Guruprasad 你得到的答案没有回答你的问题吗?

标签: c++ linux c++11 g++ c++14


【解决方案1】:

获取异常是这里的标准行为。当你移动一个 Promise 时,它​​会将 Promise 持有的共享状态移动到移动到的对象上。这使得被移动的对象没有共享状态。如果我们查看reference page of set_value(),我们会看到它的状态

例外
std::future_error 满足以下条件:

  • *this 没有共享状态。错误类别设置为no_state

如果您的 QNX 实现没有抛出异常,那么它就是不合格的。

【讨论】:

  • 我不完全确定它是否不符合标准,因为移出状态通常可能是无效状态,正常成员函数行为不当(除了破坏和复制/移动分配)。所以从技术上讲,这只是一个UB。再说一次,让对象处于无效状态也是一种不好的做法,也是糟糕的 STL 实现。
  • @ALX23z 该标准要求从对象移动到未指定但有效的状态。如果这没有发生,那么它是一个需要修复的错误实现。
  • 我记得对有效/无效/未指定状态的各种含义有一定的歧义。在每个地方,它都意味着别的东西。 IIRC 只有析构函数和复制/移动分配是绝对必要的,而其他操作可能会导致移动状态出现问题。
  • @ALX23z 除非另有说明。该标准规定,在被移出后,promise 将没有共享状态。该标准还规定,如果在调用set_value 时promise 没有任何共享状态,则将抛出异常。所以,这段代码必须抛出异常。不这样做是不合格的。
猜你喜欢
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多