Variable getting destroyed before calling lambda

时间:2015-06-25 09:57:54

标签: c++ c++11 lambda clang++ g++4.8

I'm trying to build a lambda that wraps some input functions with some pre/post actions.

  • My code works fine and pre/post actions get called correctly if I try to wrap a regular function/lambda.
  • However, when I try to apply my decorating lambda to a function that it produced before, my program crashes after complaining that the inner function was freed at some point (this is confirmed by valgrind).

What puzzles me is that the crash depends on the compiler: the code works perfectly fine with Xcode 6 clang (clang-3.6 based), but crashes on linux using clang++-3.6 and g++4.8.4.

I've made a small program that reproduces the behaviour:

#include <iostream>
#include <string>
#include <functional>

using namespace std;

typedef function<void(void)> NestedFn;

int main()
{
    // Create a cfunction
    auto lambdaFactory = [&](string title, NestedFn nestedFunc)
    {
        // title is copied to the new lambda
        return [&, title]() {
            cerr << "------------ START -----------" << endl;
            cerr << "Inside: " << title << endl;
            nestedFunc();
            cerr << "------------- END ------------" << endl;
        };
    }

    auto l1 = lambdaFactory("1", []() { cerr << "\tNest (1)" << endl; });
    auto l2 = lambdaFactory("2", []() { cerr << "\tNest (2)" << endl; });

    l1(); // Works ok, displays, START, 1, END
    l2(); // Same here

    auto dobble = lambdaFactory("Dobble", l1);
    dobble(); // Display START, Inside Dobble, START, 
              // then crashes when trying to execute nestedFunc(), ie l1()
}

What did I get wrong in the variable scope management ? And is there any reason for this program not crashing using Apple's LLVM ?

EDIT

For the record, here is the correct lambdaFactory after the correction suggested by T.C. :

auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
  return [&, title, nestedFunc]() {
        cerr << "------------ START -----------" << endl;
        cerr << "Inside: " << title << endl;
        nestedFunc();
        cerr << "------------- END ------------" << endl;
    };
};

1 个答案:

答案 0 :(得分:2)

通过调用lambdaFactory返回的lambda通过引用捕获nestedFunc,但nestedFunc是一个按值传递的函数参数,因此一旦调用它就会超出范围lambdaFactory返回,导致悬空参考。

  

这个程序有没有理由不使用Apple的LLVM崩溃?

未定义未定义的行为。您也可能使用两种不同的标准库实现(Linux上的Mac / libstdc ++上的libc ++),因此在所有内容的布局方式上可能存在差异等。