返回捕获 lambda 的 lambda 时发出 Clang 警告
Clang warning when returning a lambda-capturing lambda
下面的(简化的)代码试图包装一个 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 version 11.1.0
中收到 x86-64 clang (trunk)
的警告作为更大的回购协议的一部分,但我无法隔离该版本的故障。
this related question中的例子没有给出警告。
改进(我认为)版本:
template<typename Callable>
auto wrapCallable(Callable&& callable)
{
return [callable = std::forward<Callable>(callable)]() {
callable();
};
}
auto wrappedCallable = wrapCallable([](){ return 0; });
这会消除 godbolt 中 x86-64 clang (trunk)
的警告。我认为它应该可以安全地用于任何仿函数,任何我遗漏的东西?
问题与此代码完全相同:
SomeType& foo(int x)
{
SomeType bar{x};
return bar; // undefined behavior returning reference to local object
}
您的 lambda 正在通过引用捕获本地对象,因此当您 return 它时,这将导致未定义的行为,因为捕获的对象不再存在。
当您使用此 lambda 时,很可能程序会崩溃(如果您不走运则不会)。
所以这是你的代码中的错误,clang 正在正确地抱怨。
问题更新后编辑:
更新问题后,新代码会创建 lambda 参数的副本(或移动副本)。结果是 returned lambda 不携带对局部变量的引用,所以现在可以了。
下面的(简化的)代码试图包装一个 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 version 11.1.0
中收到 x86-64 clang (trunk)
的警告作为更大的回购协议的一部分,但我无法隔离该版本的故障。
this related question中的例子没有给出警告。
改进(我认为)版本:
template<typename Callable>
auto wrapCallable(Callable&& callable)
{
return [callable = std::forward<Callable>(callable)]() {
callable();
};
}
auto wrappedCallable = wrapCallable([](){ return 0; });
这会消除 godbolt 中 x86-64 clang (trunk)
的警告。我认为它应该可以安全地用于任何仿函数,任何我遗漏的东西?
问题与此代码完全相同:
SomeType& foo(int x)
{
SomeType bar{x};
return bar; // undefined behavior returning reference to local object
}
您的 lambda 正在通过引用捕获本地对象,因此当您 return 它时,这将导致未定义的行为,因为捕获的对象不再存在。
当您使用此 lambda 时,很可能程序会崩溃(如果您不走运则不会)。
所以这是你的代码中的错误,clang 正在正确地抱怨。
问题更新后编辑:
更新问题后,新代码会创建 lambda 参数的副本(或移动副本)。结果是 returned lambda 不携带对局部变量的引用,所以现在可以了。