From: "K.Kosako" Date: 2001-11-22T16:21:17+09:00 Subject: [ruby-dev:15239] gc.c (gc_mark_rest): declare work area as static 現在のGCのアルゴリズム(matz-sheepman)を少し変更しようと思って、 テスト用スクリプトを書いているうちに、GCが永遠に戻ってこない 現象を発見しました。(最新版です) gc_mark_rest()から再帰的に呼ぶ事のできるrb_gc_mark()の深さが、 この現象が起こる場合、一段階だけになっているのが原因で永久に 終わらないようです。 本来、一段階だけでも処理は進む筈ですが、要素に自己参照をもつ配列オブジェクトが 存在しているらしく(但しこのオブジェクトがどこで作られたものかは調べきれません でした。すみません。スクリプト実行中ではないような)、絶対に進まなくなって しまいます。 一段階しか呼べない原因は、gc_mark_rest()でローカルに定義している tmp_arryが大きいからのようなので、添付のパッチのように修正してみました。 (この現象がなくても、gc_mark_rest()が呼ばれるのはスタックに余裕がないときなので、 この修正は行ったほうが、きっと速度的にも良いと思います) Linux i386です。同じ環境でないと再現させるのは難しいかもしれません。 nestの深さを変えればできるかも。 GC::disable gc = lambda { puts "GC start..." GC::enable GC::start GC::disable puts "GC end" } def nest(level, what) if level == 0 what.call else nest(level - 1, what) end end x = nil for i in 1..100 x = [x] end nest(4470, gc) --- gc.c.orig Thu Nov 22 00:41:26 2001 +++ gc.c Thu Nov 22 15:33:27 2001 @@ -454,7 +454,7 @@ static void gc_mark_rest() { - VALUE tmp_arry[MARK_STACK_MAX]; + static VALUE tmp_arry[MARK_STACK_MAX]; VALUE *p; p = (mark_stack_ptr - mark_stack) + tmp_arry; -- 小迫@ソフネック 渋谷区恵比寿1-15-1