【发布时间】:2012-03-12 21:07:12
【问题描述】:
我有一个矩阵类型,它包含一个 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 矩阵函数(see gist) 时,我遇到了段错误。
具体来说,当我第一次尝试在 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 部分——而且我的段错误也几乎与 this trace 相同,发帖人将其归咎于 GC。
所以,我的问题:
如果是 GC,标记
VALUEs 数组的合适方法是什么?如果不是 GC,我该如何诊断这种类型的错误?我从来没有见过这样的东西。
编辑:
原来这是一个用 C 创建的 VALUEs 初始化失败的例子。
换句话说,请确保在尝试访问 a 之前执行 *(VALUE*)a = INT2FIX(0)。
我仍然认为这个问题是相关的。我还没有设法在 StackOverflow 或其他地方找到任何真正好的标记用于清洁和清除垃圾收集的示例。如果您可以提供这样的示例和/或解释,我会将其标记为该问题的正确答案。
【问题讨论】:
-
它是 Ruby 1.9.3p0(2011-10-30 修订版 33570)。
-
所以首先我会升级到 Ruby 1.9.3-p125 并检查问题是否仍然存在。 p0 中的 GC 存在一些问题。
-
p125 问题仍然存在。我将 gdb 输出添加到要点:gist.github.com/2024629#file_gdb.p125.out
-
嗯,你也可以试试 1.9.2-p290 - 我有一个类似的问题,在 1.9.3-p0 和 1.9.3-p125 中都存在。
-
不,1.9.2-p290 也不行。除了现在它不知道当前帧是什么函数:
#0 0x0000bb69 in ?? (),从st_lookup调用。 =(
标签: c ruby garbage-collection ruby-c-extension