単純なプログラミング言語用のインタプリタをCで構築しています。
インタープリターには、ガベージコレクターが組み込まれています。 GCは、ルートからリンクされているすべてのオブジェクト(コールスタック、評価スタック、ロードされたモジュールなど)にマークを付け、残りを収集します。
現在、インタープリター用の拡張DLLを作成しています。DLLは、グラフィックス(SDL)用の別のCライブラリを「ラップ」しています。このライブラリは、グラフィカルウィンドウなどのオペレーティングシステムリソースなので、インタプリタとGCが「外界」とどのように正しく統合されるかについて考える必要があります。
現在の状況では、私の言語で次のコードを書くことができ、それはうまくいきます:
_import graphics
window = graphics.new_window()
# ... all the rest
_
ただし、次のコードで問題が発生すると思われます。
_import graphics
graphics.new_window()
_
new_window()
の結果はどこにも保存されないため、ある時点で、GCはWindow
オブジェクトを収集します。収集されると、Window
オブジェクトは、GCによって呼び出されているdeallocate
実装の一部として、ネイティブリソースをOSに返します。
これがプログラミング言語にとって妥当な動作かどうかはわかりません。一方では、ウィンドウへの参照を失うと、それをリークすることはあまり意味がありません。
一方、Java=(そして、ほとんどの言語で同等の例を見つけることができると思います)で、私が正しく覚えている場合、次のようなコードを書くことが一般的で合法です(疑似Java ):
_public void makeWindow() {
new JFrame();
}
_
これにより、画面に表示され、表示されたままになるGUIウィンドウが作成されます。ご覧のとおり、JFrame
オブジェクトはどこにも保存されていません。それでも、GCはそれを収集しません(または、少なくともJFrame
がラップするOSリソースを収集しません)。
これを言語VMに実装する標準的な方法は何ですか?
私が今考えることができる唯一のアプローチは、ネイティブリソースをラップするオブジェクトが、GCによって要求されたときに、これらのリソースをnot解放することです。これらのリソースを解放する唯一の方法は、ユーザーコードでオブジェクトのdispose
メソッドを明示的に呼び出すことです。 VM実装の標準的なアプローチは何ですか?
割り当てられたオブジェクトを管理するインタプリタは、それらのオブジェクトへのポインタが格納される場所を完全に制御する必要があります。インタープリターが外部ライブラリーにインターフェースする場合、それらのライブラリー内の割り当て可能なリソースはすべて、インタープリター内でのみ管理して、単純さと信頼性を確保する必要があります。
多くの標準的なガベージコレクションスキームがあり、いずれかを選択するには、インタープリターをどの程度複雑にするか、アプリケーションがオブジェクトの収集中に0.5秒以上の一時停止を許容できるかどうか、およびその他の考慮事項を決定する必要があります。
変数、配列、オブジェクトなどの割り当てられたリソースは、ローカル関数のスタック上のローカルリソースのリストなど、ポインターを標準の場所に格納できます。スコープが終了すると、複雑なガベージコレクションスキームを必要とせずに割り当てを解除できます。
ガベージコレクションは世代と呼ばれる段階で実行できるため、必要なときにGCの半分だけを実行する必要があります。これにより、重要なアプリケーション機能中のガベージコレクションの遅延を制限できます。
言語がこれをサポートしている場合、メモリの高速割り当てと解放の1つの方法は、ガベージコレクションを完全に排除します。この方法では、多くの空きリストを使用して、ある範囲で長さが2のべき乗である空きブロックを格納します。特定のサイズのメモリを割り当てる必要がある場合、そのログは、シフトの数をカウントして、ゼロになるまで右シフトして計算されます。次に、その番号に対応する空きリストを使用してブロックが割り当てられます。ブロックは、空きリストがなくなったときにのみ分割されます。アプリケーションが非常に長時間実行される場合にのみ、フラグメンテーションが問題になる可能性がありますが、このようなアプリケーションがサポートされる場合は、このケースに対処する必要があります。
一部の言語では、リソース識別子またはポインタを保持する、いわゆるスマートポインタを定義できます。そのようなポインターがコピーされると、1つのポインターはリソースに対して「権限のある」ままであり、権限のあるポインターが削除される(または存続期間が終了する)と、リソースは解放されます。このようなポインターは、インタープリターでのサポートをほとんどまたはまったく必要とせず、コンパイルされた言語でサポートできます。
参照がない場合、ウィンドウはガベージコレクションされます。参照がない知っているで、ガベージコレクションされていない場合は、どこか不明な参照があります。
たとえば、すべてのウィンドウへの参照を保持する「画面」オブジェクトがある場合があります。