Preciso de um esclarecimento sobre o gerenciamento de memória do GTK quando removo um widget de um contêiner.
/* Create a label widget with a floating reference. */
GtkWidget *lbl_text = gtk_label_new ("Text");
/* Create a grid container widget. */
GtkWidget *grid_text = gtk_grid_new ();
/* Add the label to the grid, which replaces the floating reference with a standard reference. */
gtk_grid_attach ( GTK_GRID(grid_text), lbl_text, 0, 0, 3, 1);
Quando destruo a grade grid_text
, o GTK decrementa a contagem de referência no rótulo para zero e a memória do rótulo é liberada. Tudo bem.
O que acontece com a contagem de referência do rótulo se eu remover o rótulo da grade?
gtk_grid_remove (GTK_GRID(grid_text), lbl_text);
Agora tem lbl_text
uma contagem de referência de zero e é destruído, ou tem uma referência flutuante de um e preciso destruí-lo manualmente usando g_object_unref()
?
Podemos olhar o código fonte:
gtk_grid_remove
-->gtk_widget_unparent
-->g_object_unref
Então, a resposta rápida é que a limpeza está feita. Mas, parte do código é um pouco complexa...
Aqui está o
gtk_grid_remove
código:Até onde sei, a única decisão que poderia diminuir a contagem de árbitros seria:
gtk_widget_unparent
.Aqui está o
gtk_widget_unparent
código:Observe que a última coisa que ele faz é
g_object_unref
AFAICT, se o widget for de nível superior, a função faz um internal
g_object_ref
e theng_object_unref
antes de fazer o finalg_object_unref
. Essas são chamadas balanceadas, então provavelmente nenhuma mudança.Então, a conclusão superficial seria que a função realmente limpa as coisas.
Mas essa função é [um pouco] complexa, chamando muitas
gtk_*
funções no widget, então não consigo dizer se essa última chamada é apenas para compensar uma dessasgtk_*
chamadas que aumentam a contagem de referências.No entanto, isso pode parecer estranho para mim, então minha conclusão [ingênua/simples] é que a chamada final é
g_object_unref
fazer o que você quer.Assim, sem examinar todos os vários apelos feitos, caveat emptor ...
A melhor maneira pode ser você fazer algum truque para ter acesso ao refcount você mesmo e ver os valores antes e depois. Isso pode ser UB (use after free), mas está bom para um teste único.
Para evitar UB, você pode envolver a chamada de destruição de grade em seus pares own/artificial
g_object_ref
andg_object_unref
. Isso evitará que o objeto seja recuperado até que suag_object_unref
chamada seja feita.