简体   繁体   English

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

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

Why does this code run incorrectly?为什么这段代码运行不正确? See the function "f1".参见 function“f1”。 It assigns the "t" to std::function.它将“t”分配给 std::function。 I list 3 ways to do that.我列出了 3 种方法来做到这一点。 But the first one is error.It will output incorrect value.但是第一个是错误的。它将 output 值不正确。 If the code is complicated, the program may even crash.如果代码复杂,程序甚至可能崩溃。 I have already knew the reason is that lambda "t" is a local variable so that we must capture it by value.我已经知道原因是 lambda "t" 是一个局部变量,所以我们必须通过值来捕获它。 But such code can be compiled without errors or warnings, is there a way(any compile option?) to find such error when compiling?但是这样的代码可以在没有错误或警告的情况下编译,有没有办法(任何编译选项?)在编译时找到这样的错误?

#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;
}

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

update: Latest clang can detect very simple case, but don't work for code above.更新:最新的 clang 可以检测非常简单的情况,但不适用于上面的代码。 example:例子:

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;
}

is there a way(any compile option?) to find such error when compiling?有没有办法(任何编译选项?)在编译时找到这样的错误?

AFAIK, no common compiler will do this for you since that's far beyond the core job of a compiler. AFAIK,没有通用的编译器会为您执行此操作,因为这远远超出了编译器的核心工作。 It's not the job of a compiler to apply program data "meta" lifetime analysis (even though, depending on the optimization level, optimizers can do that in a certain way potentially but with a lot of constraints, not appropriate to replace runtime analyzer tools).应用程序数据“元”生命周期分析不是编译器的工作(尽管根据优化级别,优化器可能会以某种方式做到这一点,但有很多限制,不适合替换运行时分析器工具) .

As a best practice, lines like this作为最佳实践,像这样的行

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

should always trigger extra attention for you to handle things correctly, at least as soon as your lambda (call) exceeds its scope life time.至少在您的 lambda (调用)超过其 scope 寿命时,应始终引起您的额外注意以正确处理事情。 If you are not sure about the life time of concrete objects, you could first take use of explicit tracking via shared and weak pointers for the reference case to lvalues at least and change the scheme to raw reference usage as soon as you are convinced, that the references maintain valid (from a design point of view, not capturing by reference always only in order to avoid subtile bugs could be questioned too, since it exposes a general design flaw or the uncertainty of the author...).如果您不确定具体对象的生命周期,您可以首先通过共享和弱指针使用显式跟踪,至少将参考案例指向左值,并在您确信后立即将方案更改为原始参考使用,即引用保持有效(从设计的角度来看,不总是通过引用捕获只是为了避免微妙的错误也可能受到质疑,因为它暴露了一般的设计缺陷或作者的不确定性......)。 Of course, that still requires a runtime checking via appropriate tests.当然,这仍然需要通过适当的测试进行运行时检查。

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

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