glibのメモリ管理でlibgc(boehm gc)を使う方法

C言語版のgetbodytext.cを書いたときglibやgtkwebkitのメモリ管理が面倒だったので、libgc(BoehmGC)が使えないか調べてみました。以下、まとめ。

注: gtk(正確にはGObjectベースのもの)との組み合わせではうまくいってません

libgcは、GC_INIT()を最初によび、以下メモリ確保でGC_MALLOCなどをmallocの代わりに使うことで、freeしなくてもガーベージコレクタが機能するプログラミングを行えるライブラリです。glibでは、メモリ確保のバックエンドを切り替える機能として、g_mem_set_vtable(GMemVTable*)があり、その二つを組み合わせます。

#include <gc/gc.h>
#include <glib.h>

static void
init_gc(GMemVTable * memvtable)
{
  /* see: http://manpages.ubuntu.com/manpages/jaunty/man3/gc.3.html */
  GC_INIT();

  /* see: GMemVTable and g_mem_set_vtable
   * http://library.gnome.org/devel/glib/stable/glib-Memory-Allocation.html
   */
  memvtable->malloc = GC_malloc;
  memvtable->realloc = GC_realloc;
  memvtable->free = GC_free;
  memvtable->calloc = NULL;
  memvtable->try_malloc = NULL;
  memvtable->try_realloc = NULL;
  g_mem_set_vtable(memvtable);
}

int
main(int argc, char * argv[])
{
  GMemVTable memvtable;
  /* 以下、変数宣言 */

  init_gc(&memvtable); /* 最初に実行 */

  /* 以下、普通にglibを使う。release不要。*/
  g_thread_init(NULL);
  ...
  return 0;
}

本当はGC_DEBUG対応のため、大文字のGC_MALLOCを使うべきですが、これは引数ありマクロで参照ができないため、

gpointer gc_malloc(gsize s) { return GC_MALLOC(s); }
gpointer gc_realloc(gpointer m, gsize s) { return GC_REALLOC(m, s); }
void gc_free(gpointer m) { GC_FREE(m); }

を定義して、これを使うべきなのでしょう(さらに、GC_DEBUG時のみこれを使うよう、ifdefで定義するという手も)。


GC_MALLOC_ATOMICなる関数もあるのですが、数値や文字列のようなポインタを含まないデータで使うと効率化するもののようです(スレッド関係とは無関係でした)。

例: pywebkitgtkとjswebkitでJavaScriptを実行してJavaScript実行済みのドキュメントを得る - ラシウラC言語版をlibgc対応化

(こういったプログラムならメモリ開放はいらないけど...)

geglやpixbufをつかったりしてみたけど、セグフォがでたりうまくいかない。。。だめかなあ。