1

このコードは、Clang (Apple LLVM 4.2) ではなく GCC (4.7.2-5ubuntu) でコンパイルすると、実行時に 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デバッグ中、ラムダが で呼び出されるとクラッシュが発生しfuncます。betaラムダが呼び出されたときにまだ有効であるはずですが、無効なオブジェクトとして報告されます。

これはこのバグの結果であるかのように見えますが、そのバグは 4.7.2 で修正されたと報告されています。

編集:わかりやすくするために初期化Beta::kされていますが、バグには影響しません。

4

1 に答える 1

4

ここに 1 つの問題があります。

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

あなたのラムダは参照によってバインドfされているため(コンストラクターへの引数であり、コンストラクターに対してローカルであるため)、コンストラクターが完了した後、その参照はぶら下がっています。後で を呼び出すとg、このダングリング リファレンスが参照されるため、未定義の動作が発生します。

[&]toを値でバインドするように変更する[=]と、問題ありません。

于 2013-02-13T17:25:12.587 に答える