Undefined behavior of std :: future as a return type?

In my case, I am using std :: future as the return type, but I get undefined behavior. Code below:

#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; 
}

      

I compiled this piece of code g++-4.7.2 -std=c++11 test_future.cc -lpthread

and got the following output:

?0
0

      

But when I split debug line

above, the result is 1

(as expected). Also, if I use std::future

as a parameter with a function update

instead of a return value, I can also get the correct output result.

I want to know what the problem is. G ++ error or usage error? Thank.

+3


source to share


3 answers


The problem is that you are committing the variable c

by reference, combined with the fact that you run the lambda asynchronously. The last part means that the function update

may have returned before the lambda actually executed, and now it refers to a variable that no longer exists.

The reason this works if you have a debug line is due only to undefined behavior.



So the problem has nothing to do with what you are returning std::future

.

The obvious solution is, of course, to capture c

by value instead, and if this is not possible in your actual code, you may need to rethink your design.

+4


source


The problem is your lambda is being auto lambda = [&] () -> bool

captured by reference. The c reference can be dangling as the thread can execute after the function exits.



Instead, you must capture the value auto lambda = [=] () -> bool

.

0


source


Sounds like undefined behavior to me. You write c

by reference, but it will fall out of scope by the time it is executed lambda

.

Hence, c == 1

this is undefined behavior because it is c

out of scope. If you are committing to a value, you should be fine.

auto lambda = [c] () -> bool {
  int b = 0; 
  for(int i = 0; i < 10000000; ++i) {
    b += 1; 
  }  
  std::cout << "?" << c << std::endl;
  return c == 1; 
}; 

      

0


source







All Articles