gpt4 book ai didi

c - 应该如何在 Ruby 扩展中对 VALUE* 数组进行标记?

转载 作者:太空宇宙 更新时间:2023-11-03 16:34:38 24 4
gpt4 key购买 nike

我有一个矩阵类型,它包含一个 void* 数组,表示一个对象数组(它们在给定矩阵中都是一种类型,例如,所有 C 整数、所有 float 、 double 、各种结构,甚至可能是所有 Ruby VALUE)。

在我尝试创建一个 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 矩阵函数时出现段错误 (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。

所以,我的问题:

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

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

编辑:

事实证明,这是一个无法初始化在 C 中创建的 VALUE 的示例。

换句话说,确保在尝试访问 a 之前执行 *(VALUE*)a = INT2FIX(0)

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

最佳答案

Ruby 的标记清除 GC 分为两个阶段。

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

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

关于c - 应该如何在 Ruby 扩展中对 VALUE* 数组进行标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9674828/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com