Can you avoid GLib variant references and memory leaks when using g_variant_get?

472 views Asked by At

Background

I'm using GLib and variants.

I have this scenario where I want to get the value deep inside a variant.

The initial variant, changed_properties has the format a{sv}.

// Example 1
/* GVariant *variant = g_variant_get_variant(
        g_variant_get_child_value(g_variant_get_child_value(changed_properties, 0), 1));
*/

GVariant *changed_property = g_variant_get_child_value(changed_properties, 0);

// Example 2
GVariant *changed_property_variant = g_variant_get_variant(g_variant_get_child_value(changed_property, 1));
// Unref only frees g_variant_get_variant

// Example 3
GVariant *changed_property_variant_child = g_variant_get_child_value(changed_property, 1);

GVariant *changed_property_variant = g_variant_get_variant(changed_property_variant_child);

// Unref the objects and let reference counter get rid of used memory
g_variant_unref(changed_property_variant);
g_variant_unref(changed_property_variant_child);

What I understand

In my understanding, to extract v (which is a variant), I have first to extract the first {sv} from the array of sv dictionaries. In Example 3, I perform this in the first function call of g_variant_get_child_value(changed_properties, 0) after the commented code in Example 1.

Now I'm left with a resulting variant in the form of {sv}. To extract the variant, I have to yet again call g_variant_get_child_value(changed_property, 1) (Where index 0 is the string and index 1 is the variant in {sv} dictionary.

The issue

The issue appears when calling functions like in Example 1 and Example 2. All the references of the memory obtained from g_variant_get_child_value(), g_variant_get_variant(), except for the last call which puts the reference in the variable, are lost and cannot be unrefferenced (as in Example 3).

The question

So my question is: How can one get to the depth of v and its contents without creating so many GVariant objects and handle so much memory through references?

1

There are 1 answers

4
Philip Withnall On

If you’ve been provided with an a{sv} you are likely wanting to look up a particular key (an a{sv} is the GVariant/D-Bus representation of a key-value dictionary).

To do so, use GVariantDict, which allows indexed access by string key:

g_auto(GVariantDict) dict = G_VARIANT_DICT_INIT (changed_properties);
guint value;
if (!g_variant_dict_lookup (&dict, "key-to-look-up", "u", &value))
  g_error ("key not found");
// value from v is now in `value`

You will need to know the type of the value in advance, and pass that as the format string (third argument) to g_variant_dict_lookup().