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

内存分配和垃圾收集似乎工作正常,直到我尝试创建一个矩阵 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 矩阵函数 (见要点).

具体来说,当我第一次尝试在第一个对象上调用 Ruby 方法时,似乎出现了段错误 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 中我了解最少的部分——而且我的段错误也几乎与 这条痕迹, ,海报将其归因于 GC。

所以,我的问题是:

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

  2. 如果不是 GC,我该如何诊断此类错误?我从来没有见过这样的事情。

编辑:

原来这是一个初始化失败的例子 VALUEs 在 C 中创建。

换句话说,请确保执行以下操作 *(VALUE*)a = INT2FIX(0) 在您尝试访问之前 a.

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

有帮助吗?

解决方案

Ruby 的标记和清除 GC 分两个阶段工作。

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

然而,正如您稍后注意到的,并非任何可能的 VALUE 都是有效的 Ruby 对象。然而,我相信用 Qnil 初始化(即nil) 会更加红宝石风格。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top