GtkTree leaks `GtkRBNode` of child items when parent item is removed
Steps to reproduce
- Run the snippet below
- Observe that
GtkRBNode
of child item is never freed
Current behavior
There is a leak of GtkRBNode
Expected outcome
No leaks
Version information
GTK 3.24.25
Additional information
I understand that the leak occurs because:
-
gtk_tree_view_row_deleted()
is only called for parent row -
gtk_tree_view_row_deleted()
does not iterate children -
_gtk_rbnode_free()
does not free children.
#include <gtk/gtk.h>
int main (int argc, char **argv)
{
gtk_init(&argc, &argv);
GtkTreeStore* treestore = gtk_tree_store_new(1, G_TYPE_INT);
// There must be some other item, otherwise gtk_tree_view_row_deleted()
// will see that tree is empty and delete entire rbtree and the
// leak does not occur.
GtkTreeIter otherItem;
gtk_tree_store_append(treestore, &otherItem, NULL);
GtkTreeIter rootItem;
gtk_tree_store_append(treestore, &rootItem, NULL);
// The leak is proportional to number of children
for (int i = 0; i < 10; ++i)
{
GtkTreeIter iter;
gtk_tree_store_append(treestore, &iter, &rootItem);
}
// Time to create the tree
GtkWidget* tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(treestore));
g_object_ref_sink(tree);
// Row must be expanded to generate leaking 'GtkRBNode'
GtkTreePath* rootItemPath = gtk_tree_model_get_path(GTK_TREE_MODEL(treestore), &rootItem);
gtk_tree_view_expand_row(GTK_TREE_VIEW(tree), rootItemPath, FALSE);
gtk_tree_path_free(rootItemPath);
// It is important to remove while the Tree is still alive,
// otherwise gtk_tree_view_destroy() deletes entire rbtree and the
// leak does not occur.
gtk_tree_store_remove(treestore, &rootItem);
// Cleanup
gtk_widget_destroy(tree);
g_object_unref(tree);
g_object_unref(treestore);
return 0;
}