非静态数据成员初始化器中lambda函数的分段错误

Segmentation fault for lambda function in non-static data member initializer

本文关键字:函数 分段 错误 lambda 静态 数据成员 初始化      更新时间:2023-10-16

我不确定在非静态数据成员初始化器中捕获this的lambda函数初始化std::function时可能存在的GCC错误。这是c++标准允许的吗?

给定以下代码:

#include <functional>
#include <iostream>
template <typename T>
struct A {
      T x = 0;
      std::function<void(T)> f = [this](T v) { x = v; };
};
int main() {
      A<int> a;
      a.f(1);
      std::cout << a.x << "n";
}

在我的理解中,应该打印1。但是,当使用GCC 5.4.0或GCC 6.2.0构建时,a.f(1)会发出分段错误,因为捕获的this指针为空。

下面的替代方案如我所期望的那样工作:

  • 使用构造函数初始化列表:

    template <typename T>
    struct B {
        B() : f([this](T v) { x = v; }) {}
        T x = 0;
        std::function<void(T)> f;
    };
    
  • 没有模板:
  • struct C {
        int x = 0;
        std::function<void(int)> f = [this](int v) { x = v; };
    };
    

此外,当使用Clang 3.8.0构建时,所有三个版本的行为都如我所期望的那样,这并不意味着它不是UB。

你不能这样做:

template <typename T>
struct A {
    T x = 0;
    std::function<void(T)> f = [this](T v) { x = v; };
};

As this在定义f时不存在。需要在构造函数中初始化f,例如:

A(){ f = [this](T v){ x=v; } }

您的代码在VS2015 (windows)上编译和运行。所以这可能是一个编译错误。

此外,如果您将删除模板,它可以在http://cpp.sh/上工作试试下面的代码:

#include <functional>
#include <iostream>
struct A {
      int x = 0;
      std::function<void(int)> f = [this](int v) { x = v; };
};
int main() {
      A  a;
      a.f(1);
      std::cout << a.x << "n";
}

在cpp.sh上运行原始代码得到:

 internal compiler error: in tsubst_copy, at cp/pt.c:12569
Please submit a full bug report

所以我猜这是一个bug