glibのメモリ管理でlibgc(boehm gc)を使う方法
C言語版のgetbodytext.cを書いたときglibやgtk、webkitのメモリ管理が面倒だったので、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をつかったりしてみたけど、セグフォがでたりうまくいかない。。。だめかなあ。