コンピュータ サイエンスでは、ガベージとは、コンピュータ システムのメモリ(またはその他のシステム リソース) のデータ、オブジェクト、その他の領域で、システムまたはシステム上で実行されるプログラムによる将来の計算では使用されないものを指します。すべてのコンピュータ システムのメモリ量は限られており、ほとんどのソフトウェアはガベージを生成するため、ガベージによって占有されているメモリの割り当てを解除し、ヒープ(メモリ プール)に戻して再利用することが頻繁に必要になります。
分類
ガベージは一般に 2 つのタイプに分類されます。構文上のガベージ(プログラムのメモリ空間内にあるが、プログラムのルート セットからはアクセスできないオブジェクトまたはデータ) と意味上のガベージ(プログラム入力のどのような組み合わせでも実行中のプログラムによってアクセスされることのないオブジェクトまたはデータ) です。ガベージではないオブジェクトとデータは、ライブであると言われます。
簡単に言えば、構文上のゴミは到達できないデータであり、意味上のゴミは到達されないデータです。より正確には、構文上のゴミは参照グラフのために到達できないデータ (パスがない) であり、トレース ガベージ コレクションで説明されているように、多くのアルゴリズムによって決定でき、コードではなくデータの分析のみが必要です。意味上のゴミは、到達できない (したがって構文上のゴミでもある) ためアクセスされないデータ、または到達可能だがアクセスされないデータです。後者はコードの分析が必要であり、一般に決定不可能な問題です。
構文上のゴミは、意味上のゴミの (通常は厳密な) サブセットです。オブジェクトが別のオブジェクトへの参照を保持しながら、そのオブジェクトをまったく使用しないことは完全に可能です。
例
Java の次の単純なスタック実装では、スタックからポップされた各要素は、外部からの参照がなくなると意味的にゴミになります。[a]
パブリッククラスStack {プライベートObject [] elements ;プライベートint size ;
public Stack ( int capacity ) { elements = new Object [ capacity ] ; } public void push ( Object e ) { elements [ size ++] = e ; } public Object pop () { return elements [-- size ] ; } }
これは、elements[]にまだオブジェクトへの参照が含まれているためですが、 はクラスに対してプライベートであり、メソッドはまだポップしていない要素への参照のみを返すため、この参照を通じてオブジェクトに再度アクセスされることはありません。( をデクリメントした後、このクラスはその要素に再度アクセスすることはありません。) ただし、これを知るにはクラスのコード分析が必要であり、これは一般には決定できません。
elements[]popsize
後の呼び出しでpushスタックが以前のサイズまで再拡大され、この最後の参照が上書きされると、オブジェクトは再度アクセスできなくなるため構文上のゴミとなり、ガベージ コレクションの対象になります。
自動ガベージコレクション
参照カウントガベージ コレクションによる構文ガベージの自動収集の例は、 Pythonコマンドラインインタープリタを使用して生成できます。
>>> class Foo :
... """これは空のテストクラスです。""" ...通過... >>> bar = Foo () >>> bar <__main__.Foo オブジェクト (0x54f30)> >>> del bar
このセッションでは、オブジェクトが作成され、メモリ内の位置が表示され、オブジェクトへの唯一の参照が破棄されます。オブジェクトへの参照がなくなるため、この時点からオブジェクトを再び使用することはできません。元の参照にアクセスしようとすると、これが明らかになります。
>>> bar
トレースバック (最新の呼び出しが最後):
ファイル"<stdin>"、行1、? NameError :名前 'bar' が定義されていません
オブジェクトを参照できなくなったため、オブジェクトは役に立たなくなり、ゴミになります。Python はガベージ コレクションを使用するため、オブジェクトに使用されていたメモリを自動的に解放し、再度使用できるようにします。
>>> class Bar :
... """これは別のテスト クラスです。""" ...合格... >>> baz = Bar () >>> baz <__main__.Bar オブジェクト (0x54f30)>
Barインスタンスは現在、メモリ位置0x54f30にあります。これは、以前のオブジェクトであるFooインスタンスが配置されていた場所と同じです。Fooインスタンスが破棄され、それを格納するのに使用されていたメモリが解放されたため、インタープリタは以前と同じメモリ位置にBarオブジェクトを作成し、使用可能なリソースを有効に活用します。
効果
ガベージはヒープ メモリを消費するため、それを収集する必要があります (メモリ使用量を最小限に抑え、メモリ割り当てを高速化し、ヒープの断片化とメモリ使用量を削減することでメモリ不足エラーを防ぐため)。
ただし、ガベージの収集には時間がかかり、手動で行う場合はコーディングのオーバーヘッドが必要になります。さらに、ガベージの収集によってオブジェクトが破壊されるため、ファイナライザが呼び出され、プログラム実行の任意の時点で任意のコードが実行される場合があります。ガベージ コレクションが正しく行われない (ガベージ コレクターのエラーではなく手動のガベージ コレクションのエラーが主な原因) と、ダングリング ポインターの使用によりメモリの安全性違反 (多くの場合、セキュリティ ホールの原因となる)が発生します。
構文上のゴミは自動的に収集することができ、ガベージ コレクターは広範に研究され開発されてきました。意味上のゴミは一般に自動的に収集することができないため、ガベージ コレクション言語でもメモリ リークの原因となります。意味上のゴミの検出と除去は、通常、ヒープ プロファイラーと呼ばれる特殊なデバッグ ツールを使用して行われます。ヒープ プロファイラーを使用すると、どのオブジェクトがライブで、どのようにアクセス可能かを確認できるため、意図しない参照を削除できます。
ゴミの排除
ガベージの割り当て解除を管理する問題は、コンピュータ サイエンスではよく知られています。いくつかのアプローチが採用されています。
- 多くのオペレーティング システムは、プロセスまたはプログラムが終了するときに、そのプロセスまたはプログラムが使用したメモリとリソースを再利用します。このような環境で実行するように設計された単純なプログラムや短命のプログラムは終了し、オペレーティング システムが必要な再利用を実行できるようにします。
- 手動メモリ管理を備えたシステムまたはプログラミング言語では、プログラマーは、使用されなくなったメモリが明示的に解放されるようにする必要があります。CとC++ は、このモデルをサポートする 2 つのよく知られた言語です。
- ガベージ コレクションは、さまざまなアルゴリズムを使用して、プログラムの状態を自動的に分析し、ガベージを識別し、プログラマーの介入なしにそれを解放します。JavaやHaskellなどの多くの最新のプログラミング言語は、自動ガベージ コレクションを提供しています。ただし、これは最近開発されたものではなく、 LISPなどの古い言語でも使用されていました。
- プログラムから不要な部分を識別して削除するための型理論的アプローチ (領域推論など)に関する研究が進行中です。この問題に対する一般的な型理論的解決策はまだ開発されていません。
注記
- ^ サイズ変更と明示的な例外を省略して、Effective Java項目 6を簡略化しました。
外部リンク
- ベンジャミン・ピアース(編)、型とプログラミング言語の高度なトピック、MIT Press(2005)、ISBN 0-262-16228-8
- リチャード・ジョーンズ、ラファエル・リンス著『ガベージコレクション:自動動的メモリ管理アルゴリズム』、Wiley and Sons (1996)、ISBN 0-471-94148-4
