Я пытаюсь создать лямбду, которая оборачивает некоторые функции ввода некоторыми действиями до/после.
- Мой код работает нормально, и действия pre/post вызываются правильно, если я пытаюсь обернуть обычную функцию/лямбду.
- Однако, когда я пытаюсь применить мою декоративную лямбду к функции, которую она создала ранее, моя программа падает после жалобы на то, что внутренняя функция была освобождена в какой-то момент (это подтверждается valgrind).
Что меня озадачивает, так это то, что сбой зависит от компилятора: код отлично работает с Xcode 6 clang
(на основе clang-3.6
), но сбой в Linux с использованием clang++-3.6
и g++4.8.4
.
Я сделал небольшую программу, которая воспроизводит поведение:
#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()
}
Что я сделал не так в управлении переменными? И есть ли причина того, что эта программа не дает сбой при использовании LLVM от Apple?
ИЗМЕНИТЬ
Для справки, вот правильный lambdaFactory
после исправления, предложенного TC.:
auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
return [&, title, nestedFunc]() {
cerr << "------------ START -----------" << endl;
cerr << "Inside: " << title << endl;
nestedFunc();
cerr << "------------- END ------------" << endl;
};
};
lambdaFactory
передаются по значению, поэтому вы должны захватить их по значению, если нужно вернуть лямбду. В противном случае у вас будет оборванная ссылка, поскольку аргументы функции выходят за пределы области видимости после ее возврата. - person T.C.   schedule 25.06.2015