Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ nested lambda bug in VS2010 with lambda parameter capture?

I'm using Visual Studio 2010, which apparently has some buggy behavior on lambdas, and have this nested lambda, where the inner lambda returns a second lambda wrapped as a std::function (cf. "Higher-order Lambda Functions" on MSDN):

int x = 0;
auto lambda = [&]( int n ) 
{ 
    return std::function<void()>( 
        [&] // Note capture
        { 
            x = n; 
        } 
    ); 
};

lambda( -10 )(); // Call outer and inner lambdas

assert( -10 == x ); // Fails!

This compiles but fails at the assert. Specifically, n in the inner lambda is uninitialized (0xCCCCCCCC), but x is successfully modified to its value. If I change the inner lambda's capture clause to "[&,n]", the assert passes as expected. Is this a bug with VS2010 or have I not understood how lambda capture works?

like image 310
metal Avatar asked Jun 02 '11 14:06

metal


2 Answers

It is not a bug, since n goes out of scope after lambdas return statement, thus the capture by reference is invalidated by the time you use it.

int x = 0;
auto lambda = [&]( int n ) 
{ 
    return std::function<void()>( // n is local to "lambda" and is destroyed after return statement, thus when you call the std::function, the reference capture of n is invalid.
        [&]
        { 
            x = n; // Undefined behaviour
        } 
    ); 
};

auto tmp = lambda(-10); 
// n is no longer valid
tmp(); // calling tmp which uses reference of n which is alrdy destroyed.

assert( -10 == x ); // Fails!
like image 82
ronag Avatar answered Sep 19 '22 00:09

ronag


This is similar to the case of just returning a simple reference. The thing that caught you was the compiler did not issue an warning. So it is not a bug in the compiler, it is just a lack of a warning.

std::function<int()> F(int n)
{
    return [&]{ return n; };  //no warning
}
int& F2(int n)
{
    return n; //warning
}
like image 20
jyoung Avatar answered Sep 20 '22 00:09

jyoung