Pregunta

Tengo un tipo de matriz que contiene un void* matriz, que representa una matriz de objetos (que son todos de un tipo en una matriz determinada, por ejemplo, todos los enteros de C, todos los flotantes, dobles, una variedad de estructuras o posiblemente incluso todos los de Ruby). VALUEs).

La asignación de memoria y la recolección de basura parecen funcionar correctamente hasta que intento crear una matriz de VALUEs.

Tengo definida la siguiente función de marca:

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)));
}

Entonces solo marca si en realidad es un VALUE matriz - de lo contrario, NULL se pasa a Data_Wrap_Struct para la función de marca.

Pero obtengo un error de segmentación cuando pruebo algunos de los VALUE funciones matriciales (ver esencia).

Específicamente, parece tener un error de segmentación la primera vez que intento llamar a un método Ruby en el primer objeto del VALUE* formación:

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 es un global definido en mi Init funcionan como rb_intern("*").

Es posible que esto no sea un problema de recolección de basura, pero el GC es la parte de Ruby que menos entiendo, y mi error de segmentación también es casi idéntico a este rastro, que el cartel atribuye al CG.

Entonces, mis preguntas:

  1. Si es el GC, ¿cuál es la forma apropiada de marcar una serie de VALUE¿s?

  2. Si no es el GC, ¿cómo hago para diagnosticar este tipo de error?Nunca he visto nada igual.

EDITAR:

Resulta que este es un ejemplo de falla al inicializar VALUEs creado en C.

En otras palabras, asegúrese de hacer *(VALUE*)a = INT2FIX(0) antes de intentar acceder a.

Sigo pensando que la pregunta es relevante.No he logrado encontrar ningún ejemplo realmente bueno de marcado para la recolección de basura de limpieza y barrido, en StackOverflow o en otro lugar.Si puede proporcionar un ejemplo y/o explicación de este tipo, lo marcaré como una respuesta correcta a esta pregunta.

¿Fue útil?

Solución

El GC de marcado y barrido de Ruby funciona en dos etapas.

La primera etapa marca objetos vivos.Funciona de forma recursiva llamando a la función de marcado de cada "objeto vivo" conocido.El conjunto inicial de objetos vivos se produce escaneando la pila C de cada subproceso Ruby conocido o de cada objeto global registrado (hay una función C para registrar/anular el registro de objetos "vivos conocidos").La función de marcado del objeto X debería llamar a rb_gc_mark para cada objeto al que X hace referencia.En otras palabras, lo que haces es exactamente lo que debes hacer.

Sin embargo, como notará más adelante, ningún VALOR posible es un objeto Ruby válido.Sin embargo, creo que inicializar con Qnil (es decir,nil) sería más parecido a un rubí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top