std::future作为返回类型的未定义行为
Undefined behavior of std::future as return type?
在我的例子中,我使用std::future作为返回类型,但得到了未定义的行为。代码如下:
#include <future>
#include <iostream>
#include <pthread.h>
std::future<bool> update() {
int c = 1;
//std::cout << "?" << c << std::endl; // debug line
auto lambda = [&] () -> bool {
int b = 0;
for(int i = 0; i < 10000000; ++i) {
b += 1;
}
std::cout << "?" << c << std::endl;
return c == 1;
};
return std::async(std::launch::async, lambda);
}
int main(int argc, char *argv[])
{
auto f2 = update();
std::cout << f2.get() << std::endl;
return 0;
}
我用g++-4.7.2 -std=c++11 test_future.cc -lpthread
编译了这段代码,得到了以下输出结果:
?0
0
但是当我取消注释上面的debug line
时,输出变成了1
(正如预期的那样)。此外,如果我用std::future
作为参数,用update
函数代替返回值,我也可以得到正确的输出结果。
我想知道这里出了什么问题。g++的bug还是用法的bug?谢谢
问题是通过引用捕获变量c
,再加上异步运行lambda。最后一部分意味着update
函数可能在lambda实际运行之前已经返回,现在它引用了一个不再存在的变量。
如果您有调试行,它似乎工作的原因是因为未定义的行为。
因此,问题与您返回std::future
无关。
显而易见的解决方案当然是按值捕获c
,如果在实际代码中不可能,那么您可能需要重新考虑您的设计。
问题是您的lambda auto lambda = [&] () -> bool
是通过引用捕获的。对c的引用可能是悬空的,因为线程可以在函数退出后执行。
您可能应该改为按值auto lambda = [=] () -> bool
捕获。
对我来说,这看起来像是未定义的行为。您通过引用捕获c
,但当lambda
执行时,它已经超出了范围。
因此c == 1
是未定义的行为,因为c
已经超出了范围。如果您通过值捕获,您应该没事。
auto lambda = [c] () -> bool {
int b = 0;
for(int i = 0; i < 10000000; ++i) {
b += 1;
}
std::cout << "?" << c << std::endl;
return c == 1;
};
相关文章:
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 交换未定义数据类型中的字节顺序
- 类型特征检查 CRTP 派生,在基类中,问题是未定义的类型
- 是否可以为类设置自定义返回类型
- 具有自定义返回类型和"false"返回条件的函数?
- 在派生类中定义自定义返回类型的受保护方法
- 派生类错误:未定义的类型
- 未分配返回未定义对象类型引用的 C++ 函数的返回值时会发生什么情况
- 在从抽象类继承的模板类中正确使用未定义的类型
- 子类中使用了不完整的指针-错误:使用了未定义的类型
- C++模板,在编译时解析未定义的类型
- 错误 C2679:二进制"=":未定义采用类型右侧操作数的运算符
- 如何让 MS C++编译器识别 #include 中未定义的类型
- 有没有办法在C++函数体内定义返回类型
- 提升序列化提供未定义的类型'boost::STATIC_ASSERTION_FAILURE'
- 自定义返回类型声明
- C++错误C2027:使用未定义的类型'第二'(朋友班)
- 在 c++ 中使用字符串时出错。error C2679:二进制'<<':未定义采用类型为"类"的右操作数的运算符
- 错误C2027:使用未定义的类型-如何声明类