[#3536] Re: [ruby-list:10256] Re: for が修飾子だったら — Junichi Kurokawa <jun@...>

Reply-To: ruby-devとしました。

15 messages 1998/10/22

[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を使い切った時

などです.基本的にメモリ割当の瞬間に起きますが,予測するのは
不可能なタイミングですね.
                                まつもと ゆきひろ /:|)

In This Thread