std::future<neither::Either<int, std::string>> 分段错误
std::future<neither::Either<int, std::string>> segmentation fault
此问题中的代码使用此处的 Either<>
实现:https://github.com/LoopPerfect/neither。明确地说,我怀疑这是这个特定库的问题,否则我会在那里制造问题。
以下代码段按预期工作:
std::future<std::string> f = std::async(std::launch::async, []()
{
return "test";
}
std::cout << f.get() << std::endl;
并且以下生成分段错误:
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;
返回 left(-1)
有效,neither::Either<int, int>
对 left()
和 right()
也是有效的。我知道 std::future::get
可能会产生一个段错误,因为你已经调用了它两次,在这种情况下 std::future::valid
会在调用 get
之前 return false,但是 valid
return是真的。
我在这里遗漏了什么吗?
Is there something I'm missing here?
库未正确实现。专门针对此问题的目的,copy constructor 是错误的:
constexpr Either( Either<L, R> const& e )
: isLeft(e.isLeft) {
if(isLeft) {
leftValue = e.leftValue;
} else {
rightValue = e.rightValue; // (*)
}
}
我们不能分配给那里的 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);
}
}
或者,由于我们正在编写可被各种邪恶类型使用的通用库代码,您将需要:
::new (static_cast<void*>(std::addressof(leftValue))) L(e.leftValue);
此问题中的代码使用此处的 Either<>
实现:https://github.com/LoopPerfect/neither。明确地说,我怀疑这是这个特定库的问题,否则我会在那里制造问题。
以下代码段按预期工作:
std::future<std::string> f = std::async(std::launch::async, []()
{
return "test";
}
std::cout << f.get() << std::endl;
并且以下生成分段错误:
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;
返回 left(-1)
有效,neither::Either<int, int>
对 left()
和 right()
也是有效的。我知道 std::future::get
可能会产生一个段错误,因为你已经调用了它两次,在这种情况下 std::future::valid
会在调用 get
之前 return false,但是 valid
return是真的。
我在这里遗漏了什么吗?
Is there something I'm missing here?
库未正确实现。专门针对此问题的目的,copy constructor 是错误的:
constexpr Either( Either<L, R> const& e )
: isLeft(e.isLeft) {
if(isLeft) {
leftValue = e.leftValue;
} else {
rightValue = e.rightValue; // (*)
}
}
我们不能分配给那里的 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);
}
}
或者,由于我们正在编写可被各种邪恶类型使用的通用库代码,您将需要:
::new (static_cast<void*>(std::addressof(leftValue))) L(e.leftValue);