在GCC中编写SIGSEGV代码,但不在Clang中

Code making SIGSEGV in GCC but not Clang

本文关键字:Clang SIGSEGV GCC 代码      更新时间:2023-10-16

当使用GCC(4.7.2-5ubuntu)而不是Clang(Apple LLVM 4.2)编译时,此代码在运行时生成SIGSEGV

#include <functional>
#include <iostream>
using FuncType = std::function<int(int)>;
int func(FuncType f, int i) {
    return f(i)+1;
}
struct Alpha {
    FuncType f, g;
    Alpha(FuncType f) : f(f) {
        g = [&](int i) -> int {
            return func(f, i);
        };
    }
    int go(int i) {
        return g(i);
    }
};
struct Beta {
    int k = 0;
    Beta newBeta(int nk) {
        Beta beta = *this;
        beta.k = nk;
        return beta;
    }
};
struct Gamma {
    Beta beta;
    void go(int j) {
        auto f = [&](int i) -> int {
            int n = beta.newBeta(i).k+j;
            return n*n;
        };
        Alpha alpha(f);
        std::cout << alpha.go(beta.k) << std::endl;
    }
};
int main(int argc, char *argv[]) {
    Gamma gamma;
    gamma.go(7);
    return 0;
}

调试时,在func中调用lambda f时会发生崩溃。beta报告为无效对象,即使在调用lambda时它应该仍然有效。

看起来这似乎是这个错误的结果,但据报道,这个错误在4.7.2中得到了修复。

编辑:为清晰起见,已初始化Beta::k,不影响bug。

这里有一个问题:

Alpha(FuncType f) : f(f) {
    g = [&](int i) -> int {
        return func(f, i);
    };
}

您的lambda通过引用绑定f(构造函数的一个参数,因此是构造函数的本地参数),因此在构造函数完成后,该引用将挂起。当您稍后调用g时,会得到未定义的行为,因为它引用了这个悬空引用。

[&]更改为[=]以按值绑定,它应该是可以的。