Pergunta

Eu tenho um tipo de matriz que contém um void* matriz, que representa uma matriz de objetos (que são todos de um tipo em uma dada matriz, por exemplo, todos C números inteiros, todos os floats, doubles, uma variedade de estruturas, ou, possivelmente, até mesmo todos os Rubi VALUEs).

A alocação de memória e de coleta de lixo parece funcionar corretamente até que eu tento criar uma matriz de VALUEs.

Eu tenho a seguinte função de marcação definido:

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

Então é só marcar se é realmente um VALUE matriz — caso contrário, NULL é passada para Data_Wrap_Struct para a função de marcação.

Mas eu estou ficando um segfault quando eu testar alguns dos VALUE matriz de funções (ver gist).

Especificamente, parece segfault a primeira vez que eu tentar chamar um método Ruby sobre o primeiro objeto no VALUE* matriz:

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 é um global definido em meu Init função rb_intern("*").

É possível que este não é um problema de coleta de lixo, mas o GC é a parte do Ruby que eu entendo a menos — e a minha segfault também é quase idêntica à este rastreamento, que o cartaz atributos para o GC.

Então, minhas perguntas:

  1. Se o GC, que é a forma adequada para marcar uma matriz de VALUEs?

  2. Se não é o GC, como faço para ir sobre a diagnosticar este tipo de erro?Eu nunca vi nada parecido.

EDITAR:

Acontece que este é um exemplo de falha ao inicializar VALUEs criado em C.

Em outras palavras, certifique-se de que para fazer *(VALUE*)a = INT2FIX(0) antes de tentar acessar a.

Eu ainda acho que a questão é relevante.Eu ainda não conseguiu encontrar quaisquer realmente bons exemplos de marcação para limpar e varrer a coleta de lixo, no StackOverflow ou em outro lugar.Se você pode fornecer um exemplo e/ou explicação, eu vou marcar que como uma resposta correta para esta pergunta.

Foi útil?

Solução

Ruby mark-and-sweep GC funciona em duas fases.

A primeira fase marcas de objetos vivos.Funciona recursivamente chamando a função de marcação de cada conhecida "objetos vivos".O conjunto inicial de objetos vivos é produzido pela análise do C pilha de cada conhecida Ruby thread ou de cada registado objetos globais (existe uma função C para registar/cancelar conhecidos "ao vivo" de objectos).A função de marcação de objeto X deve, em seguida, chamar rb_gc_mark para cada objectos que X se refere.Em outras palavras, o que você faz é exatamente o que você deve fazer.

No entanto, como você percebeu, mais tarde, não qualquer VALOR possível é válido Ruby objeto.No entanto, eu acredito que a inicializar com Qnil (i.e.nil) seria mais ruby-ish.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top