5

私は参照カウンターのテクニックは知っていますが、マークスイープのテクニックについては、今日「プログラミング言語の概念」という本を読んで初めて知りました。
本によると:

ガベージ コレクションの元のマーク スイープ プロセスは、次のように動作します。ランタイム システムは、要求に応じてストレージ セルを割り当て、必要に応じてセルからポインターを切断します。ストレージの再利用 (ガベージの蓄積を許可する) に関係なく、使用可能なすべてのセルが割り当てられるまで続けます。この時点で、マーク スイープ プロセスが開始され、ヒープ内に残っているすべてのガベージが収集されます。プロセスを容易にするために、すべてのヒープ セルには、収集アルゴリズムで使用される追加のインジケーター ビットまたはフィールドがあります。

私の限られた理解では、C++ ライブラリのスマート ポインターは参照カウント手法を使用しています。この種のスマート ポインターの実装を使用する C++ のライブラリはあるのでしょうか。また、この本は純粋に理論的なものであるため、実装がどのように行われるかを視覚化することはできませんでした. このアイデアを示す例は非常に価値があります。私が間違っている場合は、私を修正してください。

ありがとう、

4

2 に答える 2

2

C++ でガベージ コレクションを使用する際の難点が 1 つあります。それは、何がポインターで、何がポインターでないかを識別することです。

コンパイラを微調整して、すべてのオブジェクト タイプにこの情報を提供できる場合は完了ですが、それができない場合は、保守的なアプローチを使用する必要があります。つまり、メモリをスキャンして、ポインター。ここでは、人々がビットをポインターに詰め込む (64 ビットでは上位ビットはほとんど使用されない) か、「スペースを節約する」ために 2 つの異なるポインターを XOR する「ビットスタッフィング」の難しさもあります。

現在、C++0x では、標準委員会がガベージ コレクションの実装を支援する標準 ABI を導入しています。n3225 では、 20.9.11 Pointer safety [util.dynamic.safety]で見つけることができます。もちろん、これは人々がそれらの関数を自分のタイプに実装することを前提としています:

void declare_reachable(void* p); // throw std::bad_alloc
template <typename T> T* undeclare_reachable(T* p) noexcept;

void declare_no_pointers(char* p, size_t n) noexcept;
void undeclare_no_pointers(char* p, size_t n) noexcept;

pointer_safety get_pointer_safety() noexcept;

実装すると、(これらの関数を定義する) ガベージ コレクション スキームをアプリケーションにプラグインする権限が与えられます。もちろん、必要な場所でこれらの操作を実際に提供するには、もちろんいくつかの作業が必要です。1つの解決策は、単純にオーバーライドすることですが、ポインター演算を考慮newdeleteていません...

最後に、ガベージ コレクションには多くの戦略があります。参照カウント (サイクル検出アルゴリズムを使用) とマーク アンド スイープが主な異なるシステムですが、さまざまな種類があります (世代別かそうでないか、コピー/圧縮かどうかなど)。

于 2011-03-04T07:42:17.453 に答える
1

彼らは今までにそれをアップグレードしたかもしれませんが、Mozilla Firefoxは、参照カウントされたスマートポインターが可能な場合に使用され、参照サイクルをクリーンアップするためにマークアンドスイープガベージコレクターが並行して実行されるハイブリッドアプローチを使用していました。完全にはわかりませんが、他のプロジェクトがこのアプローチを採用している可能性があります。

C ++プログラマーがこのタイプのガベージコレクションを回避しているのを見ることができた主な理由は、オブジェクトデストラクタが非同期で実行されることを意味するためです。つまり、ネットワーク接続や物理ハードウェアなどの重要なリソースを保持するオブジェクトが作成された場合、クリーンアップがタイムリーに実行されるとは限りません。さらに、デストラクタが共有リソースにアクセスする場合は、適切な同期を使用するように非常に注意する必要がありますが、シングルスレッドのストレート参照カウントソリューションでは、これは必要ありません。

このアプローチのもう1つの複雑さは、C ++がポインターに対する生の算術演算を可能にすることです。これにより、ガベージコレクターの実装が非常に複雑になります。この種のシステムを構築する上での大きな障壁ですが、この問題を保守的に解決することは可能です(たとえば、Boehm GCを見てください)。

于 2011-03-04T05:40:37.377 に答える