In che modo la marcatura dovrebbe essere compiuta su array di valore * in un'estensione rubino?
-
12-12-2019 - |
Domanda
Ho un tipo di matrice che contiene un'array void*
, che rappresenta una serie di oggetti (che sono tutti di un tipo in una determinata matrice, ad esempio, tutti gli interi C, tutti i galleggianti, i raddoppiati, una varietà di strutture, o possibilmente anche Tutti i VALUE
di rubino).
Assegnazione della memoria e collezione di rifiuti sembra funzionare correttamente fino a cercare di creare una matrice di generatori di VALUE
s.
Ho la seguente funzione di marchio definita:
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)));
}
.
Quindi la marcatura solo se è in realtà una matrice VALUE
, in caso contrario, NULL
viene passato a Data_Wrap_Struct
per la funzione Mark.
Ma sto ottenendo un segfault quando testo alcune delle funzioni della matrice di VALUE
(vedi GIST) .
In particolare, sembra Segfault la prima volta che provo a chiamare un metodo Ruby sul primo oggetto nell'array 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
è un globale definito nella mia funzione Init
come rb_intern("*")
.
È possibile che questo non sia un problema di raccolta della spazzatura, ma il GC è la parte di Ruby che capisco il minimo - e il mio Segfault è anche quasi identico a Questa traccia , che il poster attribuisce al GC.
Allora, le mie domande:
- .
-
Se è il GC, qual è il modo appropriato per contrassegnare una serie di
VALUE
s? -
Se non è il GC, come posso andare a diagnosticare questo tipo di errore? Non ho mai visto niente del genere.
Modifica:
si scopre che questo è un esempio di mancata inizializzazione di VALUE
s creata in c.
In altre parole, assicurati di fare *(VALUE*)a = INT2FIX(0)
prima di provare a accedere a a
.
Io penso ancora che la domanda sia rilevante. Non sono riuscito a trovare alcuni buoni esempi di marcatura per la raccolta di rifiuti puliti e spazzate, su Stackoverflow o altrove. Se è possibile fornire un tale esempio e / o spiegazione, segnerò come una risposta corretta a questa domanda.
Soluzione
Ruby's Mark-and-Sweep GC funziona in due fasi.
Il primo stadio segna gli oggetti in diretta.Funziona ricorsivamente chiamando la funzione di marcatura di ciascun "Live Objects" noto.Il set iniziale di oggetti live è prodotto scansionando la pila C di ciascun filettatura rubino nota o di ciascun oggetto globale registrato (c'è una funzione C per registrare / deregistrati oggetti "noti dal vivo").La funzione di marcatura dell'oggetto X dovrebbe quindi chiamare rb_gc_mark per ciascun oggetto a cui si riferisce.In altre parole, quello che fai è esattamente ciò che dovresti fare.
Tuttavia, come notato in seguito, non qualsiasi valore possibile è un oggetto rubino valido.Tuttavia, credo che l'inizializzazione con Qnil (I.e. Nil) sarebbe più ruby-ish.