15

プログラミング言語に含める機能を探してガベージコレクションを読んでいて、「弱いポインタ」に出くわしました。ここから:

弱ポインタ​​ーはポインターに似ていますが、弱ポインタ​​ーからの参照がガベージコレクションを妨げないこと、および弱ポインタ​​ーを使用する前に有効性をチェックする必要があることを除いて。

弱いポインタは、参照するメモリが実際にはまだ有効である可能性があるため、ガベージコレクタと相互作用しますが、弱いポインタが作成されたときとは異なるオブジェクトが含まれています。したがって、ガベージコレクターはメモリをリサイクルするたびに、それを参照する弱いポインターがあるかどうかを確認し、それらを無効としてマークする必要があります(これはこのような単純な方法で実装する必要はありません)。

弱いポインタについては今まで聞いたことがありません。私は自分の言語で多くの機能をサポートしたいと思っていますが、この場合、これが役立つケースを一生考えることはできません。弱いポインタを何に使うのでしょうか?

4

9 に答える 9

9

本当に大きなものはキャッシングです。キャッシュがどのように機能するかを考えてみましょう。

キャッシュの背後にある考え方は、メモリの負荷が非常に大きくなり、一部のオブジェクトをプッシュする必要がある(またはもちろん明示的に無効になる)まで、オブジェクトをメモリに格納することです。したがって、キャッシュリポジトリオブジェクトは、何らかの形でこれらのオブジェクトを保持する必要があります。弱参照を介してそれらを保持することにより、メモリが少ないためにガベージコレクタが消費するものを探しに行く場合、弱参照のみで参照されるアイテムがガベージコレクションの候補として表示されます。他のコードで現在使用されているキャッシュ内のアイテムは、ハードリファレンスが引き続きアクティブであるため、それらのアイテムはガベージコレクションから保護されます。

ほとんどの場合、独自のキャッシュメカニズムを使用することはありませんが、キャッシュを使用するのが一般的です。キャッシュ内のオブジェクトを参照するプロパティが必要であり、そのプロパティが長期間スコープ内にとどまるとします。オブジェクトをキャッシュからフェッチすることをお勧めしますが、オブジェクトが使用できない場合は、永続ストレージから取得できます。また、圧力が高くなりすぎた場合に、その特定のオブジェクトを強制的にメモリに残したくない場合もあります。したがって、そのオブジェクトへの弱参照を使用できます。これにより、オブジェクトが使用可能な場合はフェッチできるようになりますが、キャッシュから外れる可能性もあります。

于 2009-09-28T03:40:22.983 に答える
8

典型的なユースケースは、追加のオブジェクト属性のストレージです。固定されたメンバーのセットを持つクラスがあり、外部からさらにメンバーを追加したいとします。したがって、キーが弱参照であるディクショナリオブジェクト->属性を作成します。そうすれば、辞書はキーがガベージコレクションされるのを防ぎません。オブジェクトを削除すると、WeakKeyDictionaryの値も削除されます(コールバックなど)。

于 2009-09-28T03:44:23.380 に答える
5

言語のガベージコレクターが循環データ構造を収集できない場合は、弱参照を使用して収集できるようにすることができます。通常、相互に参照する2つのオブジェクトがあり、他の外部オブジェクトがそれら2つを参照していない場合、それらはガベージコレクションの候補になります。ただし、ナイーブなガベージコレクターは、相互の参照が含まれているため、それらを収集しません。

これを修正するには、1つのオブジェクトが2番目のオブジェクトを強く参照し、2番目のオブジェクトが最初のオブジェクトを弱参照するようにします。次に、最初のオブジェクトへの最後の外部参照がなくなると、最初のオブジェクトがガベージコレクションの候補になり、その後すぐに2番目のオブジェクトが続きます。これは、その唯一の参照が弱いためです。

于 2009-09-28T03:54:24.437 に答える
3

別の例...完全にはキャッシュされていませんが、類似しています:I / Oライブラリが、ファイル記述子をラップしてファイルへのアクセスを許可するオブジェクトを提供するとします。オブジェクトが収集されると、ファイル記述子が閉じられます。現在開いているすべてのファイルを一覧表示できるようにする必要があります。このリストに強力なポインターを使用すると、ファイルが閉じられることはありません。

于 2009-09-28T03:44:47.733 に答える
1

オブジェクトのキャッシュリストを保持したいが、オブジェクトの「実際の」所有者がそれを使用した場合にそれらのオブジェクトがガベージコレクションされるのを防ぎたい場合に使用します。

Webブラウザーには、ブラウザーが他の場所にロードして履歴/ディスクキャッシュに保存した画像オブジェクトへの参照を保持する履歴オブジェクトがある場合があります。Webブラウザーは、これらの画像の1つを期限切れにする可能性があります(ユーザーがキャッシュをクリアした、キャッシュタイムアウトが経過したなど)が、ページには引き続き参照/ポインターがあります。ページが弱参照/ポインタを使用している場合、オブジェクトは期待どおりに消え、メモリはガベージコレクションされます。

于 2009-09-28T03:43:15.473 に答える
0

弱参照を持つ重要な理由の1つは、オブジェクトが情報またはイベントのソースを1つ以上のリスナーに接続するパイプラインとして機能する可能性に対処することです。リスナーがいない場合、パイプラインに情報を送信し続ける理由はありません。

たとえば、列挙中に更新できる列挙可能なコレクションについて考えてみます。コレクションは、アクティブな列挙子に変更されたことを通知する必要がある場合があります。これにより、それらの列挙子はそれに応じて調整できます。一部の列挙子が作成者によって放棄されたが、コレクションがそれらへの強い参照を保持している場合、コレクションが存在する限り、それらの列挙子は存在し続けます(および更新通知を処理します)。コレクション自体がアプリケーションの存続期間中存在する場合、それらの列挙子は事実上永続的なメモリリークになります。

コレクションが列挙子への弱参照を保持している場合、この問題は大部分解決できます。列挙子が破棄された場合、コレクションがまだ弱い参照を保持していても、ガベージコレクションの対象になります。次回コレクションが変更されると、弱参照のリストを調べ、まだ有効なものに更新を送信し、そうでないものをリストから削除できます。

ファイナライザーといくつかの追加オブジェクトを使用して弱参照の効果の多くを達成することは可能であり、そのような実装を弱参照を使用する実装よりも効率的にすることは可能ですが、多くの落とし穴があり、バグを回避することは困難です。WeakReferenceを使用して正しいアプローチを作成する方がはるかに簡単です。このアプローチは最適に効率的ではないかもしれませんが、ひどく失敗することはありません。

于 2010-11-18T00:30:56.637 に答える
0

弱いポインタは、ポインタが指すオブジェクトの「ライフサポート」の形式にならないようにします。

ビューポートクラス、2つのUIクラス、および多数のウィジェットクラスがあるとします。UIで作成するウィジェットの寿命を制御する必要があるため、UIはSharedPtrsを制御するすべてのウィジェットに保持します。UIオブジェクトが有効である限り、それが参照するウィジェットはガベージコレクションされません(SharedPtrのおかげで)。

ただし、ビューポートは実際に描画を行うクラスであるため、UIは、ウィジェットを描画できるように、ビューポートにウィジェットへのポインターを渡す必要があります。何らかの理由で、アクティブなUIクラスを別のクラスに変更する必要があります。2つのシナリオを考えてみましょう。1つはUIがViewportWeakPtrsを通過し、もう1つはSharedPtrs(ウィジェットを指す)を通過しました。

ビューポートにすべてのウィジェットをWeakPointersとして渡した場合、UIクラスが削除されるとすぐに、ウィジェットへのSharedPointerがなくなるため、ガベージコレクションが行われるため、ビューポートがオブジェクトを参照しても、ウィジェットは保持されません。ライフサポート」。これは、そのUIを使用しなくなったため、ましてや作成されたウィジェットを使用しなくなったため、まさに必要なものです。

ここで、ビューポートをSharedPointerに渡し、UIを削除すると、ウィジェットはガベージコレクションされません。なんで?まだ生きているビューポートには、ウィジェットへのSharedPtrでいっぱいの配列(ベクトルまたはリストなど)があるためです。別のUIオブジェクトのウィジェットを制御していたUIを削除した場合でも、ビューポートは事実上、それらの「ライフサポート」の形式になりました。

一般に、言語/システム/フレームワークは、メモリ内のどこかに「強力な」参照がない限り、ガベージコレクションを行います。すべてがすべてに強い参照を持っているとしたら、ガベージコレクションは発生しません。その振る舞いが必要な場合もあれば、そうでない場合もあります。WeakPtrを使用していて、オブジェクトを指すShared / StrongPtrsが残っていない場合(WeakPtrsのみ)、WeakPtr参照にもかかわらず、オブジェクトはガベージコレクションされ、WeakPtrs(または削除または削除)がNULLに設定されます。なにか)。

繰り返しになりますが、WeakPtrを使用すると、基本的に、指定したオブジェクトもデータにアクセスできるようになりますが、WeakPtrは、SharedPtrのようにポイントするオブジェクトのガベージコレクションを妨げません。SharedPtrを考えるときは、「ライフサポート」、WeakPtr、「ライフサポート」は考えないでください。オブジェクトのライフサポートがゼロになるまで、ガベージコレクションは(通常)発生しません。

于 2014-03-31T03:09:45.637 に答える
-1

弱参照は、たとえばキャッシュシナリオで使用できます。弱参照を介してデータにアクセスできますが、データに長時間アクセスしない場合やメモリの負荷が高い場合は、GCがデータを解放できます。

于 2009-09-28T03:42:29.857 に答える
-1

ガベージコレクションの理由は、メモリ管理がプログラマーの明示的な制御下にあるCのような言語では、オブジェクトの所有権が、特にスレッド間、またはさらに難しいことに、メモリを共有するプロセス間で渡されるときに、メモリリークを回避するためです。ダングリングポインタは非常に難しくなる可能性があります。それが十分に難しい場合は、一度にメモリに収まるよりも多くのオブジェクトにアクセスする必要性にも対処する必要があります。他のオブジェクトができるように、しばらくの間一部のオブジェクトを解放する方法が必要です。メモリに入れることができます。

そのため、一部の言語(Perl、Lisp、Javaなど)は、オブジェクトの「使用」を停止できるメカニズムを提供し、ガベージコレクターは最終的にこれを検出して、オブジェクトに使用されているメモリを解放します。プログラマーがそれを間違える可能性のあるすべての方法を心配することなく、これを正しく行います(プログラマーがこれを台無しにする方法はたくさんありますが)。

オブジェクトにアクセスする回数に、オブジェクトの値を計算するのにかかる時間を概念的に掛けると、オブジェクトをすぐに利用できない場合のコストや、メモリ内の大きなオブジェクトは、いくつかの小さなオブジェクトを保持することを妨げる可能性があります。オブジェクトを3つのカテゴリに分類できます。

一部のオブジェクトは非常に重要であるため、それらの存在を明示的に管理する必要があります。それらはガベージコレクターによって管理されないか、明示的に解放されるまで収集されないようにする必要があります。一部のオブジェクトは、計算が安価で、小さく、頻繁にアクセスされないか、いつでもガベージコレクションできる同様の特性を備えています。

3番目のクラスは、再計算にコストがかかるが再計算できるオブジェクトであり、ある程度頻繁に(おそらく短時間のバーストで)アクセスされ、サイズが大きいなど、3番目のクラスです。それらは再利用される可能性があるため、できるだけ長くメモリに保持したいが、重要なオブジェクトに必要なメモリが不足したくない。これらは弱参照の候補です。

重要なリソースと競合しない場合は、これらのオブジェクトをできるだけ長く保持する必要がありますが、重要なリソースにメモリが必要な場合は、必要に応じて再計算できるため、これらのオブジェクトを削除する必要があります。これらは、弱いポインタが対象です。

この例としては、写真があります。何千枚もの写真を表示する写真のWebページがあるとします。レイアウトする画像の数を知る必要があり、リストを取得するためにデータベースクエリを実行する必要があるかもしれません。数千のアイテムのリストを保持するためのメモリはおそらく非常に小さいです。クエリを一度実行して、それを維持したいとします。

ただし、Webページのペインには、一度に数十枚の写真しか物理的に表示できません。ユーザーが見ることができない写真のビットをフェッチする必要はありません。ユーザーがページをスクロールすると、表示されている画像の実際のビットが収集されます。それらの写真を表示するには、数メガバイトが必要になる可能性があります。ユーザーがいくつかのスクロール位置の間を前後にスクロールする場合、それらのメガバイトを何度も再フェッチする必要はありません。ただし、すべての写真を常にメモリに保存することはできません。したがって、弱いポインタを使用します。

ユーザーが数枚の写真を何度も何度も見た場合、それらはキャッシュに残っている可能性があり、あなたはそれらを再フェッチする必要はありません。ただし、十分にスクロールする場合は、表示されている画像を取得できるように、メモリを解放する必要があります。弱参照では、使用する直前に参照をチェックします。それでも有効な場合は、それを使用します。そうでない場合は、それを取得するために高価な計算(フェッチ)を行います。

于 2009-09-28T05:03:59.460 に答える