TL;DR

プログラムが動的に確保したメモリのうち、不要になった領域を自動的に解放する機能。1959 年ごろ、John McCarthy が Lisp の問題を解決するために考案した。この処理を行う仕組みをガベージコレクタと呼ぶ。

なぜ必要か

メモリを手動で管理すると、解放し忘れによるメモリリーク、同じ領域を 2 回解放する二重解放、解放済みの領域を指すダングリングポインタが起こりうる。ガベージコレクションはこれらを防ぐ。一時的なオブジェクトを作ったり、スレッド間でオブジェクトを共有したりするコードも、メモリ管理を気にせずに書ける。

仕組み

代表的な方式は次のとおりである。

  • 参照カウント: オブジェクトを参照するポインタの数を数え、0 になったら解放する。循環参照を回収できない
  • マーク・アンド・スイープ: 参照をたどって到達できるオブジェクトに印を付け、到達できないものを破棄する
  • コピー GC: 同じ容量の領域をもう 1 つ用意し、生きているオブジェクトだけをコピーする。断片化も同時に解消できるが、メモリを 2 倍使い、オブジェクトのアドレスが変わる
  • 世代別 GC: 新しいオブジェクトを置く領域と古い領域に分け、新しい領域を頻繁に回収する。生き残ったオブジェクトは古い領域に移す

これらは組み合わせて使われる。たとえば世代別 GC では、コピー GC とマーク・アンド・スイープを併用する。

例

  • OCaml は世代別のガベージコレクションでメモリを管理する。
  • Go もガベージコレクタを持ち、Green Tea GC という新しい実装が試験的に提供されている。
  • Rust はガベージコレクタを持たず、所有権モデルでメモリを管理する。

注意点

多くの実装では、GC の間ほかの処理を止める(Stop-the-world)ので、リアルタイム性が求められるシステムでは使いにくい。インクリメンタル GC やコンカレント GC は、この停止時間を減らすための手法である。GC 自体もメモリと CPU を使うので、メモリの小さい機器には向かない。また、今後使わないオブジェクトへの参照を持ち続けるような設計上の問題によるメモリリークは、GC でも防げない。

関連

出典