25


11

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

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

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

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

6 Answer


61


私はこれに対する2つの異なる邪魔にならないアプローチを見ました:

  1. スマートポインタは、参照カウンタを格納するために小さなメモリブロックを割り当てます。 スマートポインタの各コピーは、実際のオブジェクトへのポインタと参照カウントへのポインタを受け取ります。

  2. オブジェクトポインタに加えて、各スマートポインタは前後のポインタを含み、それによって特定のオブジェクトへのスマートポインタの二重リンクリストを形成する。 参照カウントはリストに暗黙的に含まれています。 スマートポインタがコピーされると、リストに自分自身を追加します。 破壊されると、各スマートポインタはそれ自身をリストから削除します。 それがリストの最後のものであれば、参照されているオブジェクトも解放されます。

    http://ootips.org/yonat/4dev/smart-pointers.html[こちら]に移動して一番下までスクロールすると、これらの方法をより明確に説明する優れた図があります。


3


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

あなたは この記事を見てみることができます。 この実装はこれらをコピーした別のオブジェクトに格納します。 boostのドキュメントを見たり、http://en.wikipedia.org/を見たりすることもできます。スマートポインタに関するwiki / Smart_pointer [ウィキペディアの記事]。


2


いいえ shared_ptrは参照カウント用の追加ポインタを1つだけ保持します。

shared_ptrオブジェクトのコピーを作成するとき、それは参照の数でポインタをコピーし、それを増やし、そして含まれているオブジェクトの上にポインタをコピーします。


2


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


2


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

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


2


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

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

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

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

二重リンクリストでは、外部参照はshared_ptrに保持され、内部リンクは単にweak_ptrです。 外部参照(shared_ptr)がないときはいつでも、リストの要素は解放され、弱い参照は削除されます。 最後にすべての弱参照が削除され、各リソースへの最後の弱参照によってreference_count情報が解放されます。

上記のテキストよりも混乱が少ないです…​ 後でもう一度やります。