web-dev-qa-db-ja.com

参照カウントスマートポインタ参照カウントはどのように機能しますか?

言い換えれば、実装はどのようにカウントを追跡しますか?

キーがポインタのアドレスで値が参照の数であるすべてのshared_ptrインスタンスからアクセスできるマップのようなオブジェクトが維持されていますか? shared_ptrを実装する必要がある場合、これが私の頭に浮かぶ最初のアイデアです。

これらの参照カウントスマートポインタの場合、メモリリークの可能性はありますか?もしそうなら、どうすればそれらを回避できますか?

27
Srikanth

これに対する2つの異なる非侵入型アプローチを見てきました。

  1. スマートポインタは、参照カウンタを含むメモリの小さなブロックを割り当てます。次に、スマートポインターの各コピーは、実際のオブジェクトへのポインターと参照カウントへのポインターを受け取ります。
  2. オブジェクトポインタに加えて、各スマートポインタには前と次のポインタが含まれているため、特定のオブジェクトへのスマートポインタの二重リンクリストが形成されます。参照カウントはリストに暗黙的に含まれています。スマートポインタがコピーされると、それ自体がリストに追加されます。破棄されると、各スマートポインタはリストから自分自身を削除します。リストの最後のオブジェクトである場合は、参照されているオブジェクトも解放されます。

here に移動して一番下までスクロールすると、これらの方法をより明確に説明する優れた図があります。

65
Ferruccio

参照カウントスマートポインタを使用してメモリリークを作成するのは非常に簡単です。グラフに周期があるオブジェクトのグラフのような構造を作成するだけです。サイクル内のオブジェクトは、お互いが解放されるのを防ぎます。これは自動的に解決することはできません。たとえば、二重リンクリストを作成するときは、一度に複数のオブジェクトを削除しないように注意する必要があります。

4
sharptooth

各スマートポインタオブジェクトには、共有参照カウントが含まれています(rawポインタごとに1つ)。

this の記事をご覧ください。この実装は、これらをコピーされる別のオブジェクトに格納します。また、 ブーストのドキュメント を確認するか、スマートポインタの ウィキペディアの記事 を確認することもできます。

3
Dan

多くの回答は、参照カウントの保存方法(同じネイティブポインターを保持するすべてのshared_ptrの共有メモリに保存される)に対応していますが、ほとんどの場合、リークの問題は回避されます。

参照カウントポインタを使用してメモリリークを行う最も簡単な方法は、サイクルを作成することです。例として、すべてのポインターが少なくとも2つの要素を持つshared_ptrである二重リンクリストは、削除されないことが保証されています。外部ポインターが解放されても、内部ポインターはカウントされ、参照カウントは0に到達しません。つまり、少なくとも、最も単純な実装ではそうです。

サイクルの問題に対する最も簡単な解決策は、shared_ptr(参照カウントポインター)を、オブジェクトの所有権を共有しない弱いポインターと混合することです。

共有ポインターは、リソース(ポインター)と追加のreference_count情報の両方を共有します。弱ポインタ​​ーを使用すると、参照カウントが2倍になります。共有ポインター参照カウントと弱ポインタ​​ー参照カウントがあります。共有ポインター数が0に達するとリソースは解放されますが、reference_count情報は、最後の弱いポインターが解放されるまで存続します。

二重リンクリストでは、外部参照はshared_ptrに保持されますが、内部リンクは単にweak_ptrです。外部参照(shared_ptr)がない場合は常に、リストの要素が解放され、弱参照が削除されます。最後に、すべての弱参照が削除され、各リソースへの最後の弱ポインタ​​ーがreference_count情報を解放します。

上記のテキストよりも混乱は少ないです...後でもう一度やり直します。

いいえ。shared_ptrは、参照カウント用に1つの追加ポインターを保持するだけです。

Shared_ptrオブジェクトのコピーを作成すると、参照数を含むポインターがコピーされ、それが増加し、含まれているオブジェクトにポインターがコピーされます。

2
bayda

私が覚えている限り、Effective C++の章で扱われている参照カウントポインタの問題がありました。

原則として、参照をインクリメント/デクリメントしてポインタオブジェクトを破棄することを知っている参照を保持するクラスへのポインタを含む「ライト」ポインタクラスがあります。その参照カウントクラスは、参照されるオブジェクトを指します。

2