Как следует выполнять разметку массивов ЗНАЧЕНИЙ * в расширении Ruby?

StackOverflow https://stackoverflow.com//questions/9674828

Вопрос

У меня есть матричный тип, который содержит void* массив, представляющий массив объектов (которые все относятся к одному типу в данной матрице, например, все целые числа C, все значения с плавающей точкой, удвоения, различные структуры или, возможно, даже все Ruby VALUEы).

Выделение памяти и сборка мусора, кажется, работают корректно, пока я не попытаюсь создать матрицу VALUEs.

У меня определена следующая функция mark:

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, которую я понимаю меньше всего, и мой segfault также почти идентичен этот след, который плакат приписывает GC.

Итак, мои вопросы:

  1. Если это GC, то каков подходящий способ пометить массив VALUEс?

  2. Если это не GC, как мне приступить к диагностике этого типа ошибки?Я никогда не видел ничего подобного.

Редактировать:

Оказывается, что это пример неудачной инициализации VALUEы , созданные в C.

Другими словами, обязательно сделайте *(VALUE*)a = INT2FIX(0) прежде чем вы попытаетесь получить доступ a.

Я все еще думаю, что этот вопрос актуален.Мне не удалось найти ни одного действительно хорошего примера маркировки для очистки от мусора, в StackOverflow или где-либо еще.Если вы можете привести такой пример и / или объяснение, я отмечу это как правильный ответ на этот вопрос.

Это было полезно?

Решение

Программа Ruby mark-and-sweep GC работает в два этапа.

На первом этапе отмечаются живые объекты.Он работает рекурсивно, вызывая функцию маркировки каждого известного "живого объекта".Начальный набор живых объектов создается путем сканирования стека C каждого известного потока Ruby или каждого зарегистрированного глобального объекта (существует функция C для регистрации / отмены регистрации "известных живых" объектов).Затем функция маркировки объекта X должна вызвать rb_gc_mark для каждого объекта, на который ссылается X.Другими словами, то, что вы делаете, - это именно то, что вы должны делать.

Однако, как вы заметили позже, не любое возможное ЗНАЧЕНИЕ является допустимым объектом Ruby.Однако я считаю, что инициализация с помощью Qnil (т.е.nil) было бы больше похоже на ruby.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top