cmemory-managementcode-analysisglibgtk4

The caller of the function takes ownership of the data, and is responsible for freeing it


The note quoted in the title can often be found in the documentation of GTk4. My question is this: Is there a technical way to check a program to determine whether all relevant data has been duly released. I would like to illustrate this with an example based on the question Populating dropdown with strings in GTK4.

I tested the program as follows:

#include"dropdown-glist.h"

// callback function
void cb_test(GtkDropDown *self,GParamSpec *spec, gpointer data)
{
     GObject* object = gtk_drop_down_get_selected_item (self);
     const char *key = gtk_string_object_get_string(GTK_STRING_OBJECT(object));
     gchar *value =g_hash_table_lookup (data, key);

     g_print("select: %s  %s\n",key,value);
}

void activate (GtkApplication *app, gpointer data)
{
  GtkWidget *window;

  window =gtk_application_window_new(app);
  gtk_widget_set_size_request(window,50,50);
 
  //GHashTable persists after "activate" 
  GHashTable *hash_table = g_hash_table_new(g_str_hash,g_str_equal);

  GtkWidget *drop_down = gtk_drop_down_new(NULL,NULL);

  g_hash_table_insert(hash_table,"Key0","value0");
  g_hash_table_insert(hash_table,"Key1","value1");
  g_hash_table_insert(hash_table,"Key2","value2");
  g_hash_table_insert(hash_table,"Key3","value3");

  guint hash_size;
  /* Get the keys, which are strings, as an array */
  gpointer key_array = g_hash_table_get_keys_as_array (hash_table, &hash_size);
  /* Create a new GtkStringList model from the array of strings. */
  GtkStringList *stringlist = gtk_string_list_new (key_array); 
  /* Set the model as the source for the dropdown menu. */
  gtk_drop_down_set_model (GTK_DROP_DOWN(drop_down), G_LIST_MODEL(stringlist)); 
  // nothing selected
  gtk_drop_down_set_selected (GTK_DROP_DOWN (drop_down),GTK_INVALID_LIST_POSITION);

  //only here so that changes in the dropdown do not lead to a callback beforehand
  g_signal_connect(drop_down, "notify::selected-item", G_CALLBACK(cb_test),hash_table);

  GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10);
  gtk_box_append(GTK_BOX(box),drop_down);
  gtk_window_set_child(GTK_WINDOW(window),box);

  gtk_widget_set_visible(window,TRUE);
}

There is a technical way to check if I'm hash_table must be freed in this example?

Thanks for an explanatory response.


Solution

  • The function g_hash_table_new() https://docs.gtk.org/glib/type_func.HashTable.new.html is a "constructor", it will create a hash table on your behalf and will return a pointer to you. Like in your question, it marked as: "The called function takes ownership of the data, and is responsible for freeing it". Since you get the table via a pointer, you are responsible to "free" the table. It is an reference counted object, so If you would be able to check the refcount on the object, it should be 1. So somewhere in your program you'll have to g_hash_table_unref() or g_hash_table_destroy() it. So, regarding your question, you don't need to have a technical tool, the docs say enough, it passes you a hash table by pointer for which you are responsible.

    You could for example connect (g_signal_connect()) a function to the GioApplication::shutdown signal a pass the hashtable as data and destroy it there, a GtkApplication is a GioApplication.

    Running a debug version of your program using the valgrind tool might point to memory leak regarding the allocated hash table not being freed. You might want to use some glib/gtk valgrind suppression files though..