返回捕获lambda的lambda时发出Clang警告

以下尝试包装 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]() {  
             ^~~~~~

这是一个错误,还是我错过了什么?我x86-64 clang (trunk)在Godbolt 中收到警告,并clang version 11.1.0作为更大的回购的一部分,但我无法隔离该版本的故障。

这个相关问题中的例子没有给出警告。


改进(我认为)版本:

template<typename Callable>
auto wrapCallable(Callable&& callable)
{
    return [callable = std::forward<Callable>(callable)]() {
        callable();
    };
}

auto wrappedCallable = wrapCallable([](){ return 0; });

这沉默的警告与x86-64 clang (trunk)在godbolt。我认为它应该对任何函子安全地工作,我遗漏了什么?

回答

问题与此代码完全相同:

SomeType& foo(int x)
{
    SomeType bar{x};
    return bar; // undefined behavior returning reference to local object
}

您的 lambda 正在通过引用捕获本地对象,因此当您返回它时,这将导致未定义的行为,因为捕获的对象不再存在。

当您使用此 lambda 时,程序很可能会崩溃(如果您不走运,则不会)。

所以这是您代码中的错误,clang 正在正确抱怨。

问题更新
编辑:更新问题后,新代码会为 lambda 创建参数的副本(或移动副本)。结果是返回的 lambda 不携带对局部变量的引用,所以现在很好。


以上是返回捕获lambda的lambda时发出Clang警告的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>