【问题标题】:Why does this C++ program capturing lambda argument by reference segfault?为什么这个 C++ 程序通过引用段错误捕获 lambda 参数?
【发布时间】:2020-01-02 17:02:01
【问题描述】:

这是一个使用 gcc-8.3.0 进行段错误的最小程序,使用 -std=c++2a 编译:

struct Command {
    double x;
};

template <typename T>
struct AutoBrake {
    AutoBrake(const T& publish) : publish{ publish } {}
    const T& publish;
};

int main()
{
    int count{};
    AutoBrake brake{ [&count](const Command&) {
        count += 1;
    } };

    brake.publish(Command{ 1.1f });
}

调试显示在运行brake.publish 时访问lambda 表达式内的count 引用时崩溃。

但是如果命令结构不包含任何字段,程序运行正常:

struct Command {};
...

AFAIK 因为 Command 被当作 const 引用,所以它的生命周期应该在这里延长到 main 的末尾,所以它不应该是对临时的悬空引用。

此外,如果我不访问 lambda 中的计数,则程序不会出现段错误:

...
    int count{};
    AutoBrake brake{ [&count](const Command&) {} };
    brake.publish(Command{});
...

最后,如果我首先将 lambda 存储为变量,它不会出现段错误:

    int count{};
    auto func = [&count](const Command&) { count += 1; };
    AutoBrake brake{ func };
    brake.publish(Command{});

【问题讨论】:

标签: c++ gcc lambda


【解决方案1】:

您将悬空的 lambda 存储在 AutoBrake 中。

你可以这样做:

template <typename T>
struct AutoBrake {
    AutoBrake(const T& publish) : publish{ publish } {}
    T publish;
};

int count{};
auto lambda = [&count](const Command&) {
        count += 1;
    };
AutoBrake brake{ lambda };

您的“工作”变体只是未定义行为 (UB) 的可能输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2017-10-14
    • 2018-01-22
    相关资源
    最近更新 更多