[ruby-dev:3527] Re: GC target (Re: [ruby-list:10035] Re: Ruby/Gtk text widget)
From:
matz@... (Yukihiro Matsumoto)
Date:
1998-10-13 08:32:03 UTC
List:
ruby-dev #3527
まつもと ゆきひろです
In message "[ruby-dev:3526] Re: GC target (Re: [ruby-list:10035] Re: Ruby/Gtk text widget)"
on 98/10/13, "D.Kanda" <MAP2303@mapletown.net> writes:
| かんだです
| オブジェクトがどう保存されているのか知らないんですけれど、たぶん intern
|をキーにして表形式のように考えられるんじゃないかと思います。
|
| +----------+------------+
| | key | object |
| +----------+------------+
| | | |
なるほどね.そうだったら可能ですね.
でも,残念なことに実際にはそうはなってないんですよ.
rubyのメモリ管理機能はgc.cを見る必要があるんですが,rubyのオ
ブジェクトは heaps という配列の配列の要素です.
[heaps....]
|
+->[heap....]
|
+->[heap....]
heapのひとつの要素がオブジェクトになります.で,この要素への
ポインタでオブジェクトを指しているわけです.たとえば
&heaps[0][0]
はヒープの先頭にあるオブジェクトですね.ですから,keyからオ
ブジェクトへの表のようなものは存在しないんです.変数は大域変
数,インスタンス変数,定数,ローカル変数それぞれに異なる形式
でテーブル(のようなもの)を持っています.
GCはどうしているかというと,以下のルートから再帰的にたぐれる
オブジェクトにマークを付けて(mark phase),マークのついていな
いオブジェクトを回収(sweep)しています.
GCのルート(root)
* rb_global_variable()で登録された変数
* rubyの大域変数
* rubyのローカル変数
* Cのスタック領域
Cのスタック領域は「なにがポインタでなにが整数であるか」の情
報が存在しないので,「とりあえず全部ポインタとみなし,heapの
中を指しているものはオブジェクトの参照ということにする」とい
う方針になっています.このようなGCを保守的なGC(Conservative
GC)と呼びます.
さて,GCにともなってコアダンプするケースはいくつか考えられま
すが,主なものは
* オブジェクトがいつのまにかGCされていて
+ free cellになっていた
+ 他のオブジェクトになっていた
ので,オブジェクトの構造が違い,ポインタでないところをア
クセスしてしまった.
というものです.
落ちる場所としては
* GCの中(これはあんまりない)
* ポインタアクセスしているところ
が考えられます.で,GCがらみで変なところで落ちた場合には,基
本的に以下の順で原因を疑います.
(1) 保護し忘れた領域はないか
チェックすること:
rb_global_variable()の呼び忘れ
保護することをすっかり忘れている
Data_Wrap_Struct()のmark変数の指定がない
(2) GCがバグってるんじゃない? ^^;;;
落ちたのがGCの中でなければ,その時参照していたオブジェクト
(またはその上流)のオブジェクトの保護忘れの可能性が高いです.
GCの中の場合で落ちた場合には少々厄介で,gc_mark()を何段階か
遡って当たりをつける必要があります.
どうしてもわからない場合,問題があるのがフリーソフトウェアで
あれば,再現しそうな状況をまとめて(ソースごと)私に送って下さ
るというのもアリでしょう.
フリーでない場合には…私とコンサルティング契約を結ぶと言うの
はどうでしょう? お安くしておきます.^^;;;
| GC は特定の場所で行なわれるようになっているんですか?
| どんな条件になってるんでしょう?
GCの発生するのは
* 明示的に呼んだ時(GC.start)
* heapを使い切った時
* mallocの総計がある一定数を越えた時
* file descriptorを使い切った時
などです.基本的にメモリ割当の瞬間に起きますが,予測するのは
不可能なタイミングですね.
まつもと ゆきひろ /:|)