当我从容器中移除小部件时,我需要澄清 GTK 的内存管理。
/* 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);
当我销毁网格时grid_text
,GTK 将标签上的引用计数减为零,并释放标签的内存。一切顺利。
如果我从网格中删除标签,标签的引用计数会发生什么变化?
gtk_grid_remove (GTK_GRID(grid_text), lbl_text);
现在它lbl_text
的引用计数是否为零并且被销毁了,或者它是否有一个浮动引用,我需要使用 手动销毁它g_object_unref()
?
我们可以看一下源代码:
gtk_grid_remove
-->gtk_widget_unparent
-->g_object_unref
因此,快速的答案是清理已完成。但是,有些代码有点复杂...
以下是
gtk_grid_remove
代码:据我所知,唯一可以降低引用计数的调用是:
gtk_widget_unparent
。以下是
gtk_widget_unparent
代码:请注意,它做的最后一件事是
g_object_unref
据我所知,如果小部件是顶层的,
g_object_ref
则该函数g_object_unref
在执行最终操作之前会执行内部操作g_object_unref
。这些是平衡调用,因此可能不会发生变化。因此,粗略的结论是该功能确实可以清理一些东西。
但是,这个函数有点复杂,调用了小部件上的许多
gtk_*
函数,所以我无法判断最后一个调用是否仅仅是为了补偿其中一个gtk_*
增加引用计数的调用。然而,这对我来说似乎很奇怪,所以我的[天真/简单的]结论是,最后的调用会
g_object_unref
执行您想要的操作。因此,在没有检查所有发出的各种呼叫的情况下,买者自慎……
最好的方法可能是你自己做一些小技巧来获取引用计数的访问权限,并查看前后值。这可能是 UB(释放后使用),但对于一次性测试来说没问题。
为了防止 UB,您可以将网格销毁调用包装在您自己的/人工的
g_object_ref
和g_object_unref
对中。这将防止对象被回收,直到您g_object_unref
进行调用为止。