2

我有一个矩阵类型,它包含一个void*数组,代表一个对象数组(它们都是给定矩阵中的一种类型,例如,所有 C 整数、所有浮点数、双精度数、各种结构,甚至可能所有 Ruby VALUE) .

在我尝试创建VALUEs 矩阵之前,内存分配和垃圾收集似乎正常工作。

我定义了以下标记函数:

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_mult是在我的Init函数中定义为的全局变量rb_intern("*")

这可能不是垃圾收集问题,但 GC 是我了解最少的 Ruby 部分——而且我的段错误也几乎与此 trace相同,poster 将其归因于 GC。

所以,我的问题:

  1. 如果是 GC,那么标记 s 数组的合适方法是VALUE什么?

  2. 如果不是 GC,我该如何诊断这种类型的错误?我从来没有见过这样的东西。

编辑:

事实证明,这是一个VALUE在 C 中创建的初始化 s失败的例子。

换句话说,请务必*(VALUE*)a = INT2FIX(0)在尝试访问a.

我仍然认为这个问题是相关的。在 StackOverflow 或其他地方,我还没有找到任何真正好的标记用于清洁和清除垃圾收集的示例。如果您可以提供这样的示例和/或解释,我会将其标记为该问题的正确答案。

4

1 回答 1

1

Ruby 的 mark-and-sweep GC 分两个阶段工作。

第一阶段标记活体。它通过调用每个已知“活动对象”的标记函数递归地工作。初始的活动对象集是通过扫描每个已知 Ruby 线程或每个已注册全局对象的 C 堆栈生成的(有一个 C 函数来注册/取消注册“已知活动”对象)。然后对象 X 的标记函数应该为 X 引用的每个对象调用 rb_gc_mark。换句话说,你所做的正是你应该做的。

但是,正如您稍后注意到的,没有任何可能的 VALUE 是有效的 Ruby 对象。但是,我相信使用 Qnil(即 nil)进行初始化会更加 ruby​​-ish。

于 2012-08-14T15:57:08.550 回答