2

私はスレッドを扱っていますが、コンパイラが次のコードを最適化する方法について質問があります。

void MyClass::f(){
    Parent* p = this->m_parent;
    this->m_done = true;
    p->function();
}

pの代わりに関数を呼び出すために (スタック上またはレジスタ内で) を使用することが非常に重要ですthis->m_parent。クリーンアップ パスを実行するとすぐに別のスレッドから削除される可能性m_doneがあるため (これが原因で実際​​にクラッシュしたことがあります)、その場合、ゴミが含まれている可能性がありますが、スレッド スタック/レジスタはそのままです。truethism_parent

GCC/Linux での最初のテストでは、競合状態がないことが示されましたが、これが他のコンパイラにも当てはまるかどうかを知りたいですか?

これはgulp の場合volatileですか?私は、「揮発性」が C++ で防止する最適化の種類を調べましたか? このマルチスレッド C++ コードには「揮発性」が必要ですか? しかし、どちらも私の問題に当てはまるとは感じませんでした。

コンパイラがここで何をできるかわからないので、これに頼るのは不安です。次のようなケースが見られます。

  • いいえ/有益な最適化。ポインタthis->m_parentはスタック/レジスタに格納され、この値は後でこれを呼び出すために使用されますfunction()。これは望ましい動作です。
  • コンパイラーは削除しますpthis->m_parent、たまたまレジスターで既に使用可能であり、コンパイラーはこれを使用して呼び出しを行いますがfunction()、コンパイラー間では信頼できません。これは、別のプラットフォーム/コンパイラ バージョンに移動するバグを公開する可能性があるため、悪いことです。
  • コンパイラはへの呼び出しの前に削除pして読み取ります。これにより、私が持つことのできない競合状態が発生します。this->m_parentfunction()

ここでコンパイラが許可されていることについて、誰かが光を当てることができますか?

編集

this->m_doneそれがであることに言及するのを忘れていましたstd::atomic<bool>。私はC++ 11を使用しています。

4

3 に答える 3

1

並べ替えの問題が発生する可能性があります。この問題を解決するには、メモリ バリアを確認してください。p のロードと m_done の設定が正確にその順序で行われるように配置し (両方の命令の間に配置)、問題ないはずです。

実装は C++11 とブーストで利用できます。

于 2013-07-12T16:19:03.863 に答える
-1

ええと、メンバー関数の 1 つにいるときに、他のスレッドがオブジェクトを削除する可能性がありますか? 未定義の動作。簡潔でシンプル。

于 2013-07-12T16:30:56.430 に答える