7

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?

2 Answers 2

8

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!
Sign up to request clarification or add additional context in comments.

3 Comments

I actually think the compiler should be able to warn of this.
@mlimber : Keep in mind that VC++ 2010 implemented lambdas pre-N2927, so it's going to have many "incorrect" behaviors related to nested lambdas.
Although in this particular case (with the return) you may be correct, nested Lambda's do incorrectly lose scope in VS2010: connect.microsoft.com/VisualStudio/feedback/details/537366/… Microsoft claims to have applied a fix for this in their implementation which we'll see in a future release.
3

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.