Memory leak, dispose and finalize. What are the good practices?

Hi ! I’m learning to code GTK Applications, and I’m really struggling with the dispose and the finalize functions.
I’ve read GObject – 2.0: GObject Tutorial, I’d like to understand what to put in there and why.

Furthermore, I think that I understand the global use of these functions, they are the GObject equivalent of the C free() function, but, from browsing the code of applications using GObject like Gnome-Calandar, what I see in these functions is not what I expect.

I was thinking that all fields of any class that are pointer like, for example, GtkWidget *awidget, should be freed with g_clear_object in dispose and/or (?) finalize. Likewise, I’m not sure of where to use gtk_widget_unparent, am-I right if I say that it should be called in my custom widget class’s dispose function ?

Thanks for helping me out !!
(here is the repository of the app I’m creating to learn GTK and GObject GitHub - Xalares/gread: A little app to train for fast reading technics)

Usually, GObjectClass.dispose is the right place to release resources. However, this is the guiding principal I think of when choosing dispose vs finalize.

Does my object create things in init that it expects to be there for the lifetime of the object? If so, and the data won’t cause circular references, I pair it with finalize. This is because it can be possible, particularly with async operations or GSourceFunc that a method could get called after your dispose has been called. So unless you’ve checked your internal state at the method boundaries, you might expect something like self->items to be non-NULL which it could be if it was cleared in dispose.

If I have things that can cause circular references, I try to put that in dispose and call g_object_run_dispose() from the “most important” object in the circular graph to cause circular references to break. Of course, we generally try to avoid circular reference, but that isn’t always possible.

If they are just data objects and having NULL values on fields are fine (the vast majority of objects), just clear state in dispose.

One case where I do both, however, is when I want to maintain symmetry between init/finalize to maintain those internal invariants, but also want to ensure related objects are released. In that case, I might use something like g_hash_table_remove_all() or g_ptr_array_remove_range() in dispose but actually free the containing structure in finalize.

Hope that helps!

2 Likes

Thanks for your answer, it helps indeed. I’m more preoccupied now by the gtk behavior, I mean what are the needed method to put in dispose or finalize that are specific of gtk and needed when you subclass the widget class ?

The only things that are specific to GTK are:

  • calling gtk_widget_unparent() on direct children of your widget that you called gtk_widget_set_parent() on
  • calling gtk_widget_dispose_template() to counterbalance gtk_widget_init_template()

Both are meant to be called inside your dispose() implementation.

For versions of GTK older than 4.8, you should call gtk_widget_unparent() on template children that are direct children of your widget, instead of gtk_widget_dispose_template().

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.