2012-01-15 36 views
0

私はクロスプラットフォームをサポートすることを目指して少しプロジェクトを始めましたので、基礎OSと対話するために1.47を選択しました。私のプロジェクトではマルチスレッドが必要でしたので、私のニーズを満たすためにスレッドを少し上げました。Boost.thread可能なメモリリーク

少し私は知っていた、明らかにそのオブジェクト(?)を破壊した後にメモリにスレッドを残すか、それからある種のメモリリークの可能性があります。

ラッパーの実装では、thread型のscoped_ptrがあり、ラッパークラスのstart()関数を呼び出すとスコープ付きptrが初期化されます。実行中のスレッドはthread-> interrupt()を使用してメインスレッドから停止され、デストラクタはラッパー関数から呼び出されます。 。(その中にオペレータを持っているスレッドの手順構造のデストラクタ、()()

はここでラッパークラスの実装です: (注意:i_exceptionやその他の機能のカップルは、他のプロジェクトコンポーネントの一部である)

#define TIMED_JOIN boost::posix_time::milliseconds(1) 

namespace utils 
{ 
    struct thread_threadable 
    { 
     template<typename T> friend class ut_thread; 
    private: 
     boost::shared_ptr<thread_threadable> instance; 
    public: 
     virtual ~thread_threadable() {} 
     virtual void operator()() = 0; 
    }; 

    template<typename T = thread_threadable> 
    class ut_thread 
    { 
    public: 
     typedef T proc_t; 
    private: 
     boost::scoped_ptr<boost::thread> thr; 
     boost::shared_ptr<proc_t> proc; 
    public: 
     explicit ut_thread(const boost::shared_ptr<proc_t> &procedure) : proc(procedure) {} 
     ~ut_thread(); 

     void start(); 
     void stop(); 

     bool running() const {return this->thr.get() != NULL;} 
     proc_t &procedure() const 
     { 
      BOOST_ASSERT(this->proc.get() != NULL); 
      return *this->proc; 
     } 
    }; 
} 
typedef utils::thread_threadable threadable; 

template<typename T> 
utils::ut_thread<T>::~ut_thread() 
{ 
    if(this->thr.get() != NULL) 
    { 
     BOOST_ASSERT(this->proc.get() != NULL); 
     this->stop(); 
    } 
} 
template<typename T> 
void utils::ut_thread<T>::start() 
{ 
    if(this->thr.get() != NULL) 
     i_exception::throw_this("another thread of this procedure is already running"); 
    if(this->proc.get() == NULL) 
     i_exception::throw_this("procedure object not initialized"); 

    this->proc->instance = this->proc; 

    this->thr.reset(new boost::thread(boost::ref(*this->proc))); 
    this->thr->timed_join(TIMED_JOIN); 
} 
template<typename T> 
void utils::ut_thread<T>::stop() 
{ 
    if(this->thr.get() == NULL) 
     i_exception::throw_this("no thread was running"); 

    this->thr->interrupt(); 
    this->proc->~T(); 
    this->thr.reset(NULL); 
} 

そして、このラッパークラスの機能をチェックして、私はmain.cppににテストをした:プログラムが取得するまで私は、これらのスレッドが破壊していないことに気づい

struct my_thr : public utils::thread_threadable 
{ 
    void operator()() 
    { 
     while(true); 
    } 
}; 

int main() 
{ 
    while(true) 
    { 
     utils::ut_thread<> thr(boost::shared_ptr<threadable>(new my_thr)); 
     utils::ut_thread<> thr1(boost::shared_ptr<threadable>(new my_thr)); 
     thr.start(); 
     thr1.start(); 
     boost::this_thread::sleep(boost::posix_time::seconds(1)); 
    } 
    return 0; 
} 

た時点で、彼らはメモリに滞在します終了しました。彼らはまた 'while(true)'ステートメントを実行し続けます。

だから、私はこのような行動を引き起こす原因は何かと尋ねています。定義されたものか、バグか他の何かがありますか?全てinterrupt

+0

私はあなたのコードがやっていることは実際には得られませんが、 'shared_ptr'サイクルはありませんか? – pmr

+0

shared_ptrの有効性を確認しました。それはうまくいくはずです – weggo

答えて

3

まずのみ(わずかに再フォーマット、boost::threadsドキュメントから取ら)特定ìnterruption pointsでスレッドを停止する:

事前定義された割り込みは

以下の機能がどのし、中断点にある点スレッド boost :: thread_interrupted現在のスレッドに対して割り込みが現在の スレッドに対して有効で、割り込みが要求されている場合:

boost::thread::join() 
boost::thread::timed_join() 
boost::condition_variable::wait() 
boost::condition_variable::timed_wait() 
boost::condition_variable_any::wait() 
boost::condition_variable_any::timed_wait() 
boost::thread::sleep() 
boost::this_thread::sleep() 
boost::this_thread::interruption_point() 

あなたは何の影響も与えないはずそれにinterrupt()を呼び出して、あなたのスレッドの実行中の任意のものを持っていないので。 threadを破壊するために今すぐ

〜スレッド();

効果: *これに関連する実行スレッドがある場合は、detach()を呼び出します。これを破壊する*。

例外:何もありません。

timed_join()timed_join()あなたがスレッドで呼び出すと失敗します。なぜなら、スレッドはその実行が速く完了していないからです。したがって、join(またはdetach、ただしそれは最終結果を変更しませんでした)スレッドは、実行スレッドに関連付けられていることを意味します。破棄されました。したがって、それらは切り離されます。つまり、オブジェクトは、もはやboost::threadオブジェクトで制御できなくなっても、終了するまで実行されます。彼らは実行して無限ループなので、実行を終了するには時間がかかるかもしれません。追記として

:あなたは、後にC++ 11 std::threadsに変更することを選択した場合は、手動でjoin()またはdetach()を呼び出すことなく、それらを破壊することは有効なコードではないことに注意してください。

+0

ありがとう、コードは正しく動作します!もっと慎重に文書を読んだはずだと思います:) – weggo

関連する問題