GtkTree(List)Store manipulation section has been updated a bit to better explain handling of boxed types

8 december 2009: Update

Reference counting is now explained from regular, consumer developer point of view

Hello.

Lately, there has been quite a few question asked about memory management on this forums and gtk mailing list, so I decided to sum up that I've learned while using gtk. Here we go.

Reference counting

We know that all Gtk objects are directly or indirectly derived from GObject. One of the fundamental functionalities of GObject is (among others) reference counting, which helps programmer with memory management.

When the GObject is created, it has reference count of 1. This reference count can be increased or decreased with g_object_ref and g_object_unref functions respectively. When GObject's reference count drops to zero, it destroys itself and frees memory. But as always, there are some exceptions which will be discussed later.

Let's have a look at the life cycles of different objects. This is the code I'll be dissecting:

When we create it with gtk_list_store_new, it has reference count of 1. We own this reference, since we were the one who created this object. When we assign it to the tree view with gtk_tree_view_set_model, tree view, tree view will also own list store. After assigning store to tree view, we don't need store anymore, so we remove our reference from store using g_object_unref call (in some gtk tutorials/books this is described as "removing your own reference", since store is now owned solely by tree view). And when we quit our program, before tree view gets destroyed, it releases store which gets destroyed together with tree view.

This was the typical GObject life cycle. Now let's have a look at GtkWidget widget.

Descendants of GInitiallyUnowned

Looking at the GtkWidget hierarchy, we'll find that one of the ancestors is GInitiallyUnowned. And this introduces a little twist in reference counting. When we create an object that inherits from GInitiallyUnowned, that object has reference count of 0, but has a floating reference. This is where calls name comes from: you don't own an initial reference on newly created object.

In order to put the things to their proper place, this floating reference needs to be sinked with g_object_ref_sink, where sinking means converting floating reference to normal reference. After the sinking is done, these kind of objects behave exactly the same as normal GObjects.

So, our treeview's life goes through these phases: gtk_tree_view_new() creates new object with floating reference (no one owns this reference); gtk_container_add call adds our treeview into window which is now the owner of the tree view. When the program quits, toplevel window releases treeview (which gets destroyed).

The same principle applies to GtkTreeViewColumn and GtkCellRenderer.

What about our toplevel window? It is descendant of GInitiallyUnowned after all. GtkWindow has a special ability to sink it's own floating reference, and when we call gtk_window_new, we get a window with a reference count of 1 and no floating reference. Or said otherwise, GtkWindow behaves like GObject, despite the fact that it's derived from GInitiallyUnowned.

Strings

Glib library offers quite a few useful functions to manipulate strings. They are usually much easier to use than libc counterparts because they allocate memory for returned string for you. But you mustn't forget to free it after the resulting strings are not needed anymore. In short: if API documentation says that the function returns newly allocated string, you must free it with g_free.

This section was short, but it is important to remember this for the next section.

GtkTree(List)Store data and object properties

Operations related to storing data in stores and retrieving it can lead to quite large memory leaks, since these operations tend to be executed in loops. Operations on object properties are less problematic, but it still pays off to do them right.

GtkTree(List)Store manipulation

When populating store with gtk_tree_store_set, the data that we pass in is handled differently according to it's type:

if the data passed in is object, then store takes ownership of it

simple data types like integers and pointers are simply copied to the store (Important: when storing a pointer, only pointer is stored inside data store, data pointed to by the pointer is not copied!!)

boxed types like strings and GdkColors are first copied and pointer to the copied data is stored inside data store

In example code, text gets copied and then pointer to that copied text is stored in first column of list store. Pixbuf on the other hand is not copied, it's reference count is increased by 1 instead and the pointer to pixbuf is stored in second column of our list store.

We also need to be careful when retrieving data from store. Again, there is difference when retrieving different types of data:

when the object is retrieved, it's reference count is increased by 1 (we own one reference in this object)

simple types are copied before handed to us

boxed types are also coped before a pointer to data is handed to us

The main consequences of that are that we need to call g_object_unref on objects that we don't need anymore or free the data we retrieved from store if appropriate (you'll want to free strings and other boxed types when you don't need them any more). Note: boxed types should be freed by the appropriate function. Generic way of doing it is to call g_boxed_free on boxed type.

Manipulating object's parameters

The exactly the same principles apply as for the tree view store manipulation.

Test

My sample code suffers from memory leak. Can you find?

That's it. I hope you learned something new.

You are highly encouraged to post constructive comments, suggestions and of course corrections;-)

I found out something interesting (related to this thread) that I wanted to share. In a nutshell I had a GObject that I wanted to have a floating reference instead of the default behavior of starting with an initial reference count of 1. I found that I could use g_object_force_floating and g_object_ref_sink to get the GObject behavior to be the same as a GtkWidget.

The details then...

I have a class that extends GObject (called Document). As posted in this thread the reference count of my object automatically went to 1. However, the problem that I ran into was that the object that I wanted to "own" the reference (called Page) was in a different part of the application. By own I mean I wanted the Page to g_object_ref() and g_object_unref() the Document. See, if the count was one when I created the Document, and I called g_object_ref on it inside the Page, I now have 2 references to it. So when the Page called g_object_unref on it then the memory is not freed up because the count is only done to 1.

The solution was to call g_object_force_floating() when the Document was created. Then when the Document was set on the page I used the g_object_ref_sink() to set the reference. By forcing the reference to be floating I was able to get the behavior to be the same as a GtkWidget.

Hope this helps someone else! This thread was a big help for me in understanding what I needed to do for my app.

The leak I think (need to create a suppression file for valgrind false positives) is indeed at the line when g_strdup allocates memory for "Sample %d", i + 1. List store takes the pointer copies the array of gchar's into newly allocated memory owned by the list store; However the original copy is not g_free'd as per reference manual. One solution that springs to mind is :

Who is online

Users browsing this forum: No registered users and 6 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum