2017-05-04 10 views
1

私は、構築時にバックグラウンドタスクを実行するクラスを持っています(コンストラクタ参照)。このタスクは、その後停止され、スレッドがオブジェクトが破棄されるデストラクタで参加している:C++ブーストスレッドは、二度インスタンス化されたときにセグメンテーションフォルトを引き起こします。

// Foo.hpp ------------------------------- 
#include <boost/thread.hpp> 
#include <boost/date_time/posix_time.hpp> 

class Foo { 
    boost::thread theThread; 

    Foo(); 
    ~Foo(); 
    void bar() const; 
} 

// Foo.cpp ------------------------------- 
// This is the background task. 
void Foo::bar() const { 
    while (true) { 
    try { 
     // sleep for 1 minute. 
     boost:this_thread_sleep(boost::posix_time::minutes(1)); 

     // do other stuff endlessly 
    } 

    // boost interrupt was called, stop the main loop. 
    catch (const boost::thread_interrupted&) 
    { 
     break; 
    } 
} 

// Instantiate background task 
Foo::Foo() 
    : theThread(&Foo::bar, this) 
{ 
    // do other stuff 
} 

// Stop background task 
Foo::~Foo() { 
    theThread.interrupt() 
    theThread.join(); 
} 

私はクラスに単一のインスタンスを持っている場合さて、これは正常に動作します:

// main.cpp 
Foo f; 
// do other stuff with f 

しかし、私これを行うと、セグメンテーションフォルトと中止されたメッセージが表示されます。

// main.cpp 
Foo *f; 
f = new Foo(); // causes seg fault 
delete f; 

なぜですか?

+1

が後押し:: thread'試みをし、コンストラクタの2番目のパラメータを間接参照し 'ない(あなたのケースでは、' this') ?もしそうなら、 'this'を初期化リストの引数として使うのは安全ではないようです。 – PaulMcKenzie

+0

foo :: barがまだ構築されていないか確かにスレッド – didiz

+0

残念ですが、あなたのコードはコンパイルされず、デストラクタはプライベートなのでmain.cppでこのクラスをインスタンス化できません。このコードがあなたの問題を再現していると確信していますか? –

答えて

0

Xcodeはエラーを与える:

Attempting to use a deleted function

はFoo ::それは静的な関数ではないので、バーは、(&はFoo ::バー)上記の構文で呼び出すことはできません。それは、署名が一致しないようにする、このパラメータを隠しています。ここでは、この上の

より: pthread function from a class

また、初期化子リストにメンバ関数を使用するように悪い習慣です、動作は未定義です。ここに引用された:

Member functions (including virtual member functions) can be called from member initializers, but the behavior is undefined if not all direct bases are initialized at that point.

http://en.cppreference.com/w/cpp/language/initializer_list

次作品:

void bar(atomic_int*exit) { 
    while (*exit) { 
     // sleep for 1 minute. 
     this_thread::sleep_for(std::chrono::seconds(2)); 

     // do other stuff endlessly 

    } 
} 

class Foo { 
    thread theThread; 
    atomic_int _exit; 

public: 
    // Instantiate background task 
    Foo(): _exit(1) 
    { 
     // do other stuff 
     init(); 
    } 
    void init() 
    { 
     theThread = std::thread (&bar,&_exit); 
    } 

    // Stop background task 
    ~Foo() { 
     _exit = 0; 
     theThread.join(); 
    } 
}; 
+0

私のC++バージョンのstd :: threadやatomic型はありません。申し訳ありませんが、動作しません。 –

+0

申し訳ありませんが、私はブーストを使用していませんが、あなたがさらに見たい場合はboost :: atomic があります。いずれにしても、このようにメンバ関数を渡すことはできません。外部化または静的にする必要があります。 – didiz

関連する問題