3

今日、私は非常に奇妙なバグに遭遇しました。最小限の例を作成しました:

https://gist.github.com/SuperV1234/5792381

基本的に、一部のマシンでは、セグメンテーション違反を「テスト 2」します。他のものでは、意図したとおりに機能します。私のデスクトップ コンピューターでは、Windows 8 x64 と Linux Mint 15 x64 の両方で動作します。私のラップトップ コンピューターでは、Windows 8 x64 と Linux Mint 15 x64 の両方でセグメンテーション違反が発生します。

私を困惑させるのは:

  • 一部のマシンでは動作し、他のマシンではクラッシュするという事実
  • ラムダの内容を別の関数でラップするだけでセグメンテーション違反が修正されるという事実

これはコンパイラのバグですか? Game::test1()それとも、ラムダ本体との間に違いはありますか?

// Test 1 works
// Test 2 segfaults... on some machines.
// Compiled with -std=c++11, GCC 4.8.1, tested both on native Linux, Windows and Wine

#include <iostream>
#include <functional>
#include <vector>

using namespace std;

struct Command
{
    function<void()> func;
    void reset() { }
};

struct Timeline
{
    vector<Command*> commands;
    void clear() 
    {
        for(auto& c : commands) delete c;
        commands.clear();
    }
    void reset() { for(auto& c : commands) c->reset(); }
};

struct Game
{
    Timeline timeline;

    void test1() { timeline.clear(); timeline.reset(); }
    void run()
    {
        {
            cout << "Starting test 1..." << endl;

            Command* cmd{new Command};
            cmd->func = [&]{ test1(); };
            timeline.commands.push_back(cmd); cmd->func();

            cout << "Successfully ending test 1..." << endl;
        }

        {
            cout << "Starting test 2..." << endl;

            Command* cmd{new Command};
            cmd->func = [&]{ timeline.clear(); timeline.reset(); };
            timeline.commands.push_back(cmd); cmd->func();

            cout << "Successfully ending test 2..." << endl;
        }
    }
};

int main() { Game{}.run(); return 0; }

実際のコード (最小限の例ではありません) は、https ://github.com/SuperV1234/SSVOpenHexagon/commit/77784ae142768f964666afacfeed74300501ec07 で入手できます。

実際のコードからのバックトレース: http://paste2.org/W7yeCxOO

4

2 に答える 2

3

実行中にラムダを削除しています。まともな行為とは思えません。

あなたのコードはこれと多少同等です:

Command *c = new Command;
c->func = [&] { delete c; };
c->fun();

このようなことを本当に行う必要がある場合は、呼び出す前に関数をコピーできます。

Command *c = new Command;
c->func = [&] { delete c; };
auto f = c->func; //copy the function
f();  //c->func is deleted, but f is not!

PS: あなたは自分のclear/reset事物がそのままではほとんど意味をなさないことに気づいていますよね?

于 2013-06-16T16:42:42.110 に答える