Ruby拡張でVALUE*の配列に対してマーキングを行うにはどうすればよいですか?

StackOverflow https://stackoverflow.com//questions/9674828

質問

私は以下を含む行列型を持っています void* すべてのC整数、すべての浮動小数点数、double、さまざまな構造体、または場合によってはすべてのRubyなど、指定された行列内の1つの型のすべてであるオブ VALUEs)。

メモリ割り当てとガベージコレクションは、次の行列を作成しようとするまで正しく動作するようです VALUEs.

私は次のmark関数を定義しています:

void mark_dense_storage(void* s) {
  size_t i;
  DENSE_STORAGE* storage = (DENSE_STORAGE*)s;
  if (storage && storage->dtype == RUBY_OBJECT)
    for (i = 0; i < count_dense_storage_elements(s); ++i)
      rb_gc_mark(*((VALUE*)(storage->elements + i*sizeof(VALUE)));
}

だから、それは実際にある場合にのみマーキングを行います VALUE 行列—それ以外の場合, NULL に渡されます Data_Wrap_Struct マーク機能の場合。

しかし、私はいくつかをテストするときにsegfaultを取得しています VALUE 行列関数 (要点を参照).

具体的には、最初のオブジェクトでRubyメソッドを呼び出そうとしたときに初めてsegfaultようです VALUE* 配列:

C[i+j*ldc] = rb_funcall(C[i+j*ldc], nm_id_mult, 1, beta); // C[i+j*ldc] = C[i+j*ldc]*beta

nm_id_mult 私の中で定義されたグローバルです Init として機能 rb_intern("*").

これはガベージコレクションの問題ではない可能性がありますが、GCは私が最も理解していないRubyの一部であり、私のsegfaultもほぼ同じです このトレース, これは、ポスターがGCに属性を付けます。

だから、私の質問:

  1. それがGCの場合、配列をマークする適切な方法は何ですか VALUEs?

  2. GCでない場合、このタイプのエラーを診断するにはどうすればよいですか?私はそれのようなものを見たことがありません。

編集:

これは初期化に失敗した例であることが判明しました VALUECで作成されたs.

言い換えれば、必ず次のようにしてください *(VALUE*)a = INT2FIX(0) アクセスしようとする前に a.

私はまだ質問が関連していると思います。私は、stackoverflowや他の場所で、クリーンアンドスイープガベージコレクションのマーキングの本当に良い例を見つけることができませんでした。あなたがそのような例や説明を提供することができれば、私はこの質問に対する正しい答えとしてそれをマークします。

役に立ちましたか?

解決

Rubyのmark-and-sweep GCは2つの段階で動作します。

最初のステージはライブオブジェクトをマークします。これは、既知の各「ライブオブジェクト」のマーキング関数を呼び出すことによって再帰的に機能します。ライブオブジェクトの初期セットは、既知の各Rubyスレッドまたは登録された各グローバルオブジェクトのCスタックをスキャンすることによって生成されます(「既知のライブ」オブジェクトを登録/登録解除するC関数があります)。オブジェクトXのマーキング関数は、xが参照する各オブジェクトに対してrb_gc_markを呼び出す必要があります。言い換えれば、あなたがすることはまさにあなたがすべきことです。

しかし、後で気づいたように、可能な値は有効なRubyオブジェクトではありません。しかし、私はQnilで初期化すると信じています(つまりnil)はもっとrubyっぽいでしょう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top