From f1eeeff8cfea1001a1791ba95782ba7bbed3b976 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 26 Nov 2017 08:45:45 +0000 Subject: [PATCH] Memory leak: add a columns_finalize() method. My custom GTK layout class 'Columns' includes a linked list of dynamically allocated data, and apparently I forgot to write a destructor that frees it all when the class is deallocated, and have never noticed until now. --- unix/gtkcols.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/unix/gtkcols.c b/unix/gtkcols.c index e8223a72..ef060d63 100644 --- a/unix/gtkcols.c +++ b/unix/gtkcols.c @@ -8,6 +8,11 @@ static void columns_init(Columns *cols); static void columns_class_init(ColumnsClass *klass); +#if !GTK_CHECK_VERSION(2,0,0) +static void columns_finalize(GtkObject *object); +#else +static void columns_finalize(GObject *object); +#endif static void columns_map(GtkWidget *widget); static void columns_unmap(GtkWidget *widget); #if !GTK_CHECK_VERSION(2,0,0) @@ -96,11 +101,11 @@ static gint (*columns_inherited_focus)(GtkContainer *container, static void columns_class_init(ColumnsClass *klass) { #if !GTK_CHECK_VERSION(2,0,0) - /* GtkObjectClass *object_class = (GtkObjectClass *)klass; */ + GtkObjectClass *object_class = (GtkObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; GtkContainerClass *container_class = (GtkContainerClass *)klass; #else - /* GObjectClass *object_class = G_OBJECT_CLASS(klass); */ + GObjectClass *object_class = G_OBJECT_CLASS(klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); GtkContainerClass *container_class = GTK_CONTAINER_CLASS(klass); #endif @@ -111,6 +116,7 @@ static void columns_class_init(ColumnsClass *klass) parent_class = g_type_class_peek_parent(klass); #endif + object_class->finalize = columns_finalize; widget_class->map = columns_map; widget_class->unmap = columns_unmap; #if !GTK_CHECK_VERSION(2,0,0) @@ -149,6 +155,50 @@ static void columns_init(Columns *cols) cols->spacing = 0; } +static void columns_child_free(gpointer vchild) +{ + ColumnsChild *child = (ColumnsChild *)vchild; + if (child->percentages) + g_free(child->percentages); + g_free(child); +} + +static void columns_finalize( +#if !GTK_CHECK_VERSION(2,0,0) + GtkObject *object +#else + GObject *object +#endif + ) +{ + Columns *cols; + + g_return_if_fail(object != NULL); + g_return_if_fail(IS_COLUMNS(object)); + + cols = COLUMNS(object); + +#if !GTK_CHECK_VERSION(2,0,0) + { + GList *node; + for (node = cols->children; node; node = node->next) + if (node->data) + columns_child_free(node->data); + } + g_list_free(cols->children); +#else + g_list_free_full(cols->children, columns_child_free); +#endif + + cols->children = NULL; + +#if !GTK_CHECK_VERSION(2,0,0) + GTK_OBJECT_CLASS(parent_class)->finalize(object); +#else + G_OBJECT_CLASS(parent_class)->finalize(object); +#endif +} + /* * These appear to be thoroughly tedious functions; the only reason * we have to reimplement them at all is because we defined our own @@ -406,6 +456,7 @@ void columns_add(Columns *cols, GtkWidget *child, childdata->colspan = colspan; childdata->force_left = FALSE; childdata->same_height_as = NULL; + childdata->percentages = NULL; cols->children = g_list_append(cols->children, childdata); cols->taborder = g_list_append(cols->taborder, child);