metal
metal

Reputation: 6332

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?

Upvotes: 7

Views: 1955

Answers (2)

jyoung
jyoung

Reputation: 5161

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
}

Upvotes: 3

ronag
ronag

Reputation: 51255

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!

Upvotes: 8

Related Questions