下面尝试包装lambda的(简化的)代码给了我一些Clang版本的警告,但不是所有版本,也不是gcc版本。
template<typename Lambda>
auto wrapLambda(Lambda lambda)
{
return [&lambda]() {
lambda();
};
}
auto wrappedLambda = wrapLambda([](){ return 0; });
warning: address of stack memory associated with parameter 'lambda' returned [-Wreturn-stack-address]
return [&lambda]() {
^~~~~~
这是一个窃听器,还是我遗漏了什么?我在godbolt和clang 11.1.0
版本中收到了x86-64 clang(trunk)
的警告,这是一个更大的回购的一部分,但我还无法隔离该版本的故障。
这个相关问题中的例子没有给出警告。
改进(我认为)版本:
template<typename Callable>
auto wrapCallable(Callable&& callable)
{
return [callable = std::forward<Callable>(callable)]() {
callable();
};
}
auto wrappedCallable = wrapCallable([](){ return 0; });
这将使Godbolt中的x86-64 clang(trunk)
的警告沉默。我想它应该能安全地适用于任何一个functor,任何我遗漏的东西?
问题与此代码完全相同:
SomeType& foo(int x)
{
SomeType bar{x};
return bar; // undefined behavior returning reference to local object
}
lambda是通过引用捕获本地对象的,所以当您返回它时,这将导致未定义的行为,因为捕获的对象不再存在。
当你使用这个lambda时,程序很可能会崩溃(如果你不走运的话就不会崩溃)。
所以这是你代码中的bug,clang是正确的抱怨。