std :: future的未定义行为作为返回类型?

时间:2015-06-25 11:28:15

标签: c++ c++11 asynchronous pthreads future

就我而言,我使用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 ++的错误或使用的错误?感谢。

3 个答案:

答案 0 :(得分:4)

问题是你通过引用捕获变量c,并结合异步运行lambda。最后一部分意味着update函数可能在lambda实际运行之前返回,现在它引用了一个不再存在的变量。

如果您有调试行,似乎的原因是因为未定义的行为

因此问题与您返回std::future没有任何关系。

显而易见的解决方案当然是按值捕获c,如果在实际代码中不可能,则可能需要重新考虑您的设计。

答案 1 :(得分:0)

问题是你的lambda auto lambda = [&] () -> bool是通过引用捕获的。对c的引用可能是悬空,因为线程可以在函数退出后执行。

您可能应该按价值auto lambda = [=] () -> bool进行捕捉。

答案 2 :(得分:0)

对我来说,这看起来像是未定义的行为。您通过引用捕获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; 
};