2

オブジェクトの配列を表す配列を含む行列型がありvoid*ます(たとえば、すべてのC整数、すべてのfloat、double、さまざまな構造体、場合によってはすべてのRubyなど、特定の行列の1つの型すべてですVALUE) 。

sの行列を作成しようとするまで、メモリ割り当てとガベージコレクションは正しく機能しているようVALUEです。

次のマーク関数を定義しています。

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

VALUEしかし、いくつかの行列関数をテストすると、セグメンテーション違反が発生します(要点を参照)

VALUE*具体的には、配列の最初のオブジェクトでRubyメソッドを初めて呼び出そうとすると、セグメンテーション違反が発生するようです。

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_multInit私の関数でとして定義されたグローバルrb_intern("*")です。

これはガベージコレクションの問題ではない可能性がありますが、GCは私が最も理解していないRubyの一部です。また、私のセグメンテーション違反も、投稿者がGCに起因するこのトレースとほぼ同じです。

だから、私の質問:

  1. VALUEGCの場合、 sの配列をマークする適切な方法は何ですか?

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

編集:

VALUEこれは、 Cで作成されたsの初期化に失敗した例であることがわかりました。

つまり、*(VALUE*)a = INT2FIX(0)にアクセスする前に必ず実行してくださいa

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

4

1 に答える 1

1

RubyのマークアンドスイープGCは2段階で機能します。

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

ただし、後で気付いたように、可能なVALUEは有効なRubyオブジェクトではありません。ただし、Qnil(つまり、nil)で初期化すると、よりルビーっぽくなると思います。

于 2012-08-14T15:57:08.550 に答える