Boehm GC ライブラリを使って C/C++ でもガベージコレクションしよう

作成日:2002.10.9
修正日:2004.01.8


Boehm GC ライブラリとは

ここで、 Boehm GCと呼ぶのは H. Boehm、A. Demers、M. Weiser の 3 人によって 書かれた保守的(conservative)ガーベージコレクション (Garbage Collection;GC)ライブラリのことです。

Java の登場によって GC も人口に膾炙してきました。 しかし、多くの人がまだ 専用のプログラム言語とインタプリタ ランタイムが なければ GC は使えないと考えています。 Boehm GC ライブラリは、 従来の C 言語の malloc 関数を GC_malloc 関数へ置き換え free 関数を取り除くだけで、 C 言語のプログラムでも GC が使えるようになるという素敵なライブラリです。
当然、 C++ 言語にも対応しています。 また、あなたの作った インタプリタ処理系に Boehm GC ライブラリを組み込めば、 自動的に GC が利用可能になります。

Boehm GC は、 ほとんどの UNIX 系 OS、Win9x 系、NT系、OS/2、Amiga OS、 Mac OS 8・9に対応しています。
(ただし、OS / CPU によって機能制限を受けることがあります。)

Boehm GC のページ "A garbage collector for C and C++"は、 現在 ここ にあります。

ガーベージコレクション

GC について もう1度おさらいをします。
C/C++ では malloc (または new)によって動的に確保されたメモリは、 free (または delete) によって 明示的に解放する必要があります。
このような明示的なメモリ確保には、 バグを生み出す原因となる いろいろ問題が生じます。
メモリリーク(memory leak)


すでに不用になったメモリを 解放し忘れたまま、 その領域への参照(ポインタ)を失った状態。 C/C++ では、 1度 参照(ポインタ)を失ってしまった メモリ領域は 解放ができなくなります。
{
  {
    char* p = (char*)malloc( SIZE ); /* (1) */
  }
  
  /* 変数 p がスコープの外に出ると、(1) によって確保された
     メモリ領域は解放不能 */
}
この場合、 プログラムが終了するまで回収できない メモリ領域が プロセス中に残ることになります。 これをメモリリークと呼びます。 メモリリークが積もって行くと、 使用可能なメモリが増えてゆき、 プログラムを停止せざるえなくなります。

ダングリングポインタ(dangling pointer)


ポインタが不正なメモリ領域を指している状態を ダングリングポインタと呼びます。
特に C / C++ ではポインタに任意の値を代入できるので、 様々なタイプのダングリングポインタが発生します。
void foo(char** p) {
  char c;
  *p = &c;
}

char* p = NULL;
foo(&p);
/* p は不正なメモリアドレスを指している */
ダングリングポインタの中で 最も発見が見つけ辛いのが、 本来 正常なオブジェクトを指していたポインタが、 参照しているオブジェクトが解放されたために ダングリングポインタを指してしまうパターンです。
char* p = (char*) malloc(SIZE);
free(p);

char* q = (char*) malloc(SIZE);

/* p は不正なメモリアドレスを指している */
/* もしかすると p == q で、p を書き直すと q の内容が変わるかも */
解放された領域が、 次回以降のメモリ割り付けで再利用されている場合、 不正な書き変えを行ってしまいます。
このように メモリの解放には危険がつきまといます。 そこで free や delete のようにプログラムが明示的に解放を指示するのではなく、 プログラム自体が不要になったオブジェクトを判断して、 自動的に回収を行う機構がガーベージコレクションです。

インストール

まず、 ソースコードが必要です。 ここから ソースコードを持ってきましょう。 現在の最新バージョンは 6.1、ファイル名は gc6.1.tar.gz です。 ここでは、 UNIX 系 OS でのインストール方法について説明します。
> tar xzvf gc6.1.tar.gz
> cd gc6.1/ > ./configure > make > make check > su # make install
ライブラリを使うために必要な include ファイルはインストールされていません。 gc6.1/include の下のファイルを、適当なディレクトリにコピーしておきましょう。
# cp -r  include /usr/local/include/gc
LD_LIBRARY_PATH にライブラリをインストール先のディレクトリを入れます。 (Linux なら ld.so.conf にインストール先のディレクトリを追加して、 ldconfig コマンドを実行しましょう。)

更新履歴:
2004.01.08 dangling pointer の例が間違っているとの指摘をいただいたので修正。

戻る
Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp