あおきです。

  In mail "[ruby-ext:00691] Re: (gtk) testgtk/ctree"
    Yasushi Shoji <yashi / yashi.com> wrote:

> やすしです。

> 自分の落ちる(落ちた)原因の解釈としては
> 
> row.dataに渡された Ruby objectへ GCの root([ruby-dev: 3527]参照)から、再
> 帰的にたぐれなくなったために(cの stackから消えたから?)、memoryが解放され
> る。その後、row.dataを accessしたときに落ちる。
> 
> で、nodeを解放するときに、row.dataが Ruby objectの場合、row.destroy ==
> NULL にしておいても、Ruby objectは GCの対象になる(hashなどからの参照も消
> えれば)ので、ほっといても leakしない。
> 
> なのですが、どこで勘違いしてるのでしょうか?
> # rb_gc_mark()は、objectに markを付けて、sweepの対象外にする?

そうです。
Rubyは生成したオブジェクトを全部知っていて、そのなかの生きていることが
確実なオブジェクトから再帰的にポインタをたどり、生きオブジェクトを
探索します。マーク関数は、Rubyが知らない構造体の中にある VALUE を
教えてやるために使われます。

つまり、マーク関数が呼ばれた時点で、ruby-gtk オブジェクトは生きていた
(Rubyから参照している)ことは確実です。つまり、そのマーク関数でマーク
している row.data も Ruby からは直接、間接に参照されており、
これまでには解放されていないはずです。
また、Gtk 側からも直接 row.data を解放したりはしないので
(Gtkには解放の仕方がわからないから当然)、row.data はまだ生きているはずです。
つまり、落ちるのは row.data 自体を触ったからではないと言えます。

で、実際に試してみると、なんとNULLになってたのは GTK_CTREE_ROW(node)でした。
node と GTK_CTREE_ROW(node) は全然別物、というとこがポイントです。
^^^^              ^^^
(つまり、ぼくの前回の解釈もやはり間違っている。)
結局、最終的な解決方法は以下のようになりました。

# 五十嵐さん何度もごめんなさい (__);;
-------------------------------------------------------------------
あおきみねろう

--- org.ctree	Fri Dec  3 17:42:17 1999
+++ rbgtkctree.c	Fri Dec 10 19:46:33 1999
@@ -6,8 +6,10 @@
 ctree_node_mark(node)
      GtkCTreeNode *node;
 {
-    if (GTK_CTREE_ROW(node) && GTK_CTREE_ROW(node)->row.data)
-	rb_gc_mark(GTK_CTREE_ROW(node)->row.data);
+    if (node)
+	if (GTK_CTREE_ROW(node))
+	    if (GTK_CTREE_ROW(node)->row.data)
+	        rb_gc_mark(GTK_CTREE_ROW(node)->row.data);
 }
 
 VALUE