4

スコット・マイヤーズが教えてくれたのを覚えています

func(shared_ptr(new P), shared_ptr(new Q));

(私の記憶が正しければ)メモリ割り当て参照カウント(構築)、および関数パラメータへの割り当ての順序により、まれな状況で(理論的には?)リークが発生する可能性があるためです。これを防ぐには、関数呼び出しでをカプセル化する必要があります。 shared_ptrmake_shared()

func(make_shared<P>(), make_shared<Q>());

ここにもそれに関するいくつかの議論があります。

フィールドに(現在の)コンパイラがあるかどうかを知りたいのですが、特定のシステムでは、実際にいくつかのエラーケースでいくつかの穴が残る可能性がありますか? それとも、それらの時代は過ぎ去りましたか、それとも理論上のものに過ぎませんでしたか?

最も興味深いのは、これらのいずれかにその問題があるかどうかを知ることです。

  • g++ 4.x または g++ 2.95、Linux i386、x64、ARM、m68k、または任意の Windows
  • i368、x64、または ARM 上の Visual C++
  • Linux 上の Clang/LLVM、またはそのプラットフォームのいずれか
  • Sun または IBM、HP-UX の C++ コンパイラはどうですか?

特定のプラットフォームでこの動作を観察した人はいますか?

4

4 に答える 4

0
func(shared_ptr(new P), shared_ptr(new Q));

C++ コンパイラは、次の順序でこれを自由に実装できます。

  1. 新しいQ
  2. 新しいP
  3. 割り当てられた P の周りに shared_ptr を構築する
  4. 割り当てられた Q の周りに shared_ptr を構築する
  5. 関数を呼び出す

(コンパイラは、1 が 4 の前にあり、2 が 3 の前にある限り、1、2、3、および 4 を任意の順序で実行できます)。

上記の順序で、 ifのコンストラクターまたはthrowsPの呼び出しはメモリ リークです (メモリは割り当てられていますが、その周りに はまだ構築されていません)。newQshared_ptr

そのため、std::make_shared(割り当ての例外を適切に処理する)を呼び出す必要std::make_sharedがあり、それらの 1 つに対して が返されたときにshared_ptrが完全に構築され、リークしないことがわかっています。

特定のシステムで、実際にいくつかのエラーケースでいくつかの穴を残す可能性のある(現在の)コンパイラがフィールドにあるかどうかを知りたいですか?

標準準拠のコンパイラはすべて、この動作をします。

于 2013-08-06T08:59:49.677 に答える
0

両方のnew操作が最初に実行され、次に のコンストラクターに渡されますshared_ptrが、どちらのshared_ptrコンストラクトが最初に指定されるかは指定されていないため、新しく作成されたオブジェクトの 1 つがメモリ リークを引き起こす可能性があります。

于 2013-08-06T08:51:51.743 に答える