FIG-021

ガベージコレクション — 辿れないものはゴミ

OS・低レイヤ 2026.06.15 公開 読了 約11分

プログラムが作ったオブジェクトは、使い終わったら片付けないとメモリがどんどん埋まっていきます。でも「もう使わない」と人間が毎回宣言するのは面倒だし、消し忘れるとメモリリーク、まだ使うものを消すとクラッシュ。そこで多くの言語は、不要なオブジェクトを自動で回収する仕組み=ガベージコレクション(GC)を持っています。

では、GCはどうやって「もう使わない」を見分けるのでしょう? 答えは「ルートからたどり着けるか」だけ。たどり着けるものは生存、たどり着けないものはゴミ。下の図1で参照の線(✂のついた線)を切って、辿れなくなったオブジェクトがマーク&スイープで回収される様子を見てください。

HEAP — ルートからの参照をたどれるオブジェクトだけが生き残る
✂ 切る ✂ 切る ルート A B C D E F
未判定 マーク済み(生存) 回収(ゴミ)
MARK & SWEEP
参照の線を切って、GCを実行してみよう
F は最初からどこからも参照されていません(=すでにゴミ)。✂ のついた線をクリックすると参照を切れます。たとえば「ルート→B」を切ると、B も、Bからしか辿れない E も、まとめてゴミになります。
生存(到達可能)
回収したゴミ
図1 — マーク&スイープ:ルートから辿れるものに印→印のないものを回収

「使うか」ではなく「辿れるか」で決める

GCは、オブジェクトが将来本当に使われるかは分かりません。代わりに「いま、ルート(実行中の変数やグローバル)から参照をたどって到達できるか」という、機械的に判定できる基準を使います。到達できなくなった瞬間、そのオブジェクトは二度と使えない=ゴミだと確定するからです。

マーク&スイープはこれを2段階で行います。マーク=ルートから参照をたどり、届いた全部に「生存」の印をつける。スイープ=ヒープ全体を見回り、印のないものを回収する。この方式の強みは、循環参照(AとBが互いを参照し合う)でも、ルートから辿れなければちゃんと回収できること。単純な参照カウント方式が苦手とするケースを正しく片付けられます。

用語ミニ辞書
ルート
たどり始めの起点。実行中のスタック上の変数やグローバル変数など。
到達可能性
ルートから参照をたどって届けるか。届かないオブジェクトがゴミ。
参照カウント
参照された数を数える別方式。手軽だが循環参照を回収できない弱点がある。

まとめ

ガベージコレクションは「片付け忘れ」をなくす代わりに、回収のタイミングで処理が一瞬止まる(GCポーズ)などのコストを払っています。だからこそ、不要になった参照は早めに手放す(変数にnullを入れる、スコープを小さく保つ)ことが、メモリを無駄に抱え込まないコツになります。GCの判断基準が「辿れるかどうか」だと分かっていれば、なぜ参照を切ることが大事なのかも腑に落ちるはずです。