2011-08-29 1 views
0

このコードの動作を理解したいと思います。変数aが破壊ではないのでboost ::スレッドと含まれているクラスのデストラクタ

class Foo 
{ 
     public: 
      Foo(); 
      ~Foo(); 
      void run(); 
      int* get(); 
    private: 
      int *a; 
}; 

Foo::Foo() 
{ 
    a=NULL;  
} 
void Foo::run() 
{ 
     if (a==NULL) 
      a = new int[30000]; 
} 

int* Foo::get() 
{ 
    return a; 
} 

Foo::~Foo() 
{ 
    cout << "destructor called" << endl; 
    if (a!=NULL) 
      delete a; 
} 

int main() 
{ 
     Foo *a = new Foo(); 

     boost::thread Foothread(&Foo::run, a); 
     // Some very long computation that sometimes access 

     int *b = a->get(); 
     cout << *b << endl; 
     //Foothread.join(); 
     //delete a; 
     //Foothread.join(); 

     return 0; 
} 

このコードは120000バイトのメモリリークが発生するので、私は明示的にそれを削除すると、リークdisappers、すべてがOKでなければなりません。

私は動的に割り当てる代わりに、静的な割り当てを使用すると、デストラクタは何度も呼び出されます!!!

int main() 
{ 
     Foo a; 

     boost::thread Foothread(&Foo::run, a); 
     // Some very long computation that sometimes access "a" 
     Foothread.join(); 
     int *b = a.get(); 
     cout << *b << endl; 

     return 0; 
} 

と出力に含まが呼び出さ デストラクタが、今と呼ばれる0 デストラクタが、今と呼ばれる0 デストラクタが、今0 デストラクタが0 と呼ばれたされたされたされました、今と呼ばれる0 デストラクタ、今と呼ばれる0 デストラクタは、0 今と呼ばれる0 デストラクタは、今すぐ0 0x75e300 を0 ありましたされたされたされましたセグメンテーションエラー

デストラクタはN回呼び出されます。

ここでは、boost :: threadを使ってクラスメンバ変数とオブジェクトの両方を安全に割り当てる方法と割り当てを解除する方法と、スレッドデストラクタがクラスデストラクタを明示的に処理しない理由を知りたいと思います。

誰かが私にヒントを与えることができますか? :: smart_ptrが私を助けなければならない? mallocでメモリを割り当てる必要があります(古いC APIを使用する必要があるため)。スレッドセーフな方法は何ですか?

答えて

1

両方のバージョンがスレッド1にFooクラスのオブジェクトを作成し、バックグラウンドスレッド(スレッド2)からそのrunメソッドを呼び出します。 runが返ってくると、このバックグラウンドスレッドは終了します。

runは、実際にはクラスFooのオブジェクトを初期化します。あなたのコードの1つの問題は、いくつかの非常に長い計算を行うことがあります。時には "1" の前ににアクセスします。の前にスレッド2がaの初期化を完了しました。競合状態が発生します。これを避けるには、Foo::aaでアクセスする前にFoothread.join()に電話する必要があります。

他のいくつかのポイント:フー::〜Fooの()についてのポインタがで削除する必要がありますNULL

  • newで作成された配列aから異なっを削除するかどうかをチェックする必要はありませんで

    • delete[] a;
  • +0

    私は定期的に "a"に含まれているデータにアクセスしたい場合、私は最初にスレッドに参加する必要があります、にアクセスし、再びスレッドをデタッチ? これはプログラムのパフォーマンスにどのような影響を及ぼしますか? (私は更新データにglutプログラムの中にアクセスデータが含まれています) – linello

    +0

    'join'を実行すると、スレッドは結合されたスレッドが終了するのを待ちます。ポイントは:あなたの例では、 'Foo :: run'が終了した後(' Foothread'はもはや実行されていません)、マルチスレッドはありません。初期化が完了するまで、 'Foo :: a'にアクセスすることは安全ではありません。実際には、あなたのメインスレッドが、初期化された 'Foo'オブジェクトを必要としない**いくつかの作業をしていない限り、マルチスレッドを行う必要は全くありません。 – Stephan

    +0

    okですが、ここで実行されるメソッドは、キーが押されるまで終了してはいけません。この場合、メモリがどのように解放され、スレッドが破棄されるのでしょうか?どちらの順番で? – linello

    1

    &の場合は2番目の場合ですか?

     
    boost::thread Foothread(&Foo::run, &a); 
    
    +0

    はい、コンパイラでboost :: thread Foothread(&Foo :: run、a)を使用することもできます。 O_O非常に奇妙な – linello

    関連する問題