std :: future <both ::无论是<int,std :: string >>分段错误

Dav*_*tag 4 c++ either c++14

此问题中的代码使用Either<>此处的实现:https://github.com/LoopPerfect/neither.为了清楚起见,我怀疑这是一个特定库的问题,否则我会在那里创建一个问题.

以下代码段按预期工作:

std::future<std::string> f = std::async(std::launch::async, []()
{
    return "test";
}

std::cout << f.get() << std::endl;
Run Code Online (Sandbox Code Playgroud)

以下生成分段错误:

std::future<neither::Either<int, std::string>> f = std::async(std::launch::async, []()
{
    return neither::Either<int, std::string>(neither::right(std::string("test")));
});

neither::Either<int, std::string> v = f.get(); // Segmentation fault
std::cout << v.right().value << std::endl;
Run Code Online (Sandbox Code Playgroud)

返回left(-1)作品一样,neither::Either<int, int>两个left()right().我知道std::future::get可能会产生一个段错误就是你已经调用了两次,在这种情况下,它std::future::valid会在调用之前返回false get,但valid返回true.

这里有什么我想念的吗?

Bar*_*rry 11

这里有什么我想念的吗?

库未正确实施.特别是出于这个问题的目的,复制构造函数是错误的:

constexpr Either( Either<L, R> const& e )
  : isLeft(e.isLeft) {
  if(isLeft) {
    leftValue = e.leftValue;
  } else {
    rightValue = e.rightValue; // (*)
  }
}
Run Code Online (Sandbox Code Playgroud)

我们不能分配到this->rightValue那里,std::string在那个地方没有存在 - 我们有未初始化的记忆.

一个正确的拷贝构造函数将是:

Either(Either<L, R> const& e)
  : isLeft(e.isLeft)
{
  if(isLeft) {
    new (&leftValue) L(e.leftValue);
  } else {
    new (&rightValue) R(e.rightValue);
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,因为我们正在编写可以被各种邪恶类型使用的通用库代码,所以你需要:

::new (static_cast<void*>(std::addressof(leftValue))) L(e.leftValue);
Run Code Online (Sandbox Code Playgroud)

  • @Gaetano`struct L {void operator&(); };` (3认同)