繁体   English   中英

如何检查 c++ lambda 是否被正确捕获?

[英]How to check if the c++ lambda is captured correctly?

为什么这段代码运行不正确? 参见 function“f1”。 它将“t”分配给 std::function。 我列出了 3 种方法来做到这一点。 但是第一个是错误的。它将 output 值不正确。 如果代码复杂,程序甚至可能崩溃。 我已经知道原因是 lambda "t" 是一个局部变量,所以我们必须通过值来捕获它。 但是这样的代码可以在没有错误或警告的情况下编译,有没有办法(任何编译选项?)在编译时找到这样的错误?

#include <iostream>
#include<functional>

struct aa
{
    int a = 2000;
    void f()
    {
        ++a;
        printf("data = %d\n", a);
    }
};

std::function<void()> gf;
template<typename T>
void f1(T t)
{

    1 //gf = [&] {t(); };
    2 //gf = [=] {t(); };
    3 //gf=t;
}

int main(int argc, char** argv)
{
    aa b2;
    f1([&] {b2.f(); });
    gf();
    return 0;
}

在线测试: https://godbolt.org/z/5bqGeof58

更新:最新的 clang 可以检测非常简单的情况,但不适用于上面的代码。 例子:

auto f(int a)
{
    return [&]{return a;};  //warning: address of stack memory associated with parameter 'a' returned [-Wreturn-stack-address]
}
int main(int argc, char** argv)
{
    printf("%d\n",f(300)());
    return 0;
}

有没有办法(任何编译选项?)在编译时找到这样的错误?

AFAIK,没有通用的编译器会为您执行此操作,因为这远远超出了编译器的核心工作。 应用程序数据“元”生命周期分析不是编译器的工作(尽管根据优化级别,优化器可能会以某种方式做到这一点,但有很多限制,不适合替换运行时分析器工具) .

作为最佳实践,像这样的行

gf = [&] {t(); };

至少在您的 lambda (调用)超过其 scope 寿命时,应始终引起您的额外注意以正确处理事情。 如果您不确定具体对象的生命周期,您可以首先通过共享和弱指针使用显式跟踪,至少将参考案例指向左值,并在您确信后立即将方案更改为原始参考使用,即引用保持有效(从设计的角度来看,不总是通过引用捕获只是为了避免微妙的错误也可能受到质疑,因为它暴露了一般的设计缺陷或作者的不确定性......)。 当然,这仍然需要通过适当的测试进行运行时检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM