代码制作SIGSEGV在GCC但不是Clang

时间:2013-02-13 16:43:11

标签: c++ gcc c++11 clang sigsegv

此代码在使用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;
}

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

看起来这是this bug的结果,但据报道该错误已在4.7.2中修复。

修改:为了清晰起见,已初始化Beta::k,不会影响错误。

1 个答案:

答案 0 :(得分:4)

这里有一个问题:

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

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

[&]更改为[=]以按值绑定,它应该没问题。