Saturday, November 29, 2014

GLib: Transfer Full

While reading the GLib Reference Manual, or any other manuals for glib based libraries such as GObject, Gtk+ or GStreamer, you might notice that some parameters or returns are annotated as Transfer Full. The glib reference manual explains in the annotation glossary as

Free data after the code is done.

What exactly does this mean? This means that all responsibility of the objects that annotated variables point to will be transferred to the other side beyond the API borders.

GObject Introspection Reference Manual or GObject-Introspection Annotations Wiki has a much better description of the annotation, including other modes.

Returns

When a function of the return is annotated, you are the one to control the life of the returned object. You decide when to free() or not. All the responsibility is fully transferred to you after the function returned.

Out Parameters

This is similar to the returns. Everything is transferred to you. Free when you do need them any more.


/* -*- compile-command: "gcc -Wall -Wextra -g $(pkg-config --cflags --libs gio-2.0) transfer-full-out.c" -*- */
#include <gio/gio.h>
#include <stdio.h>

int main()
{
        GFile *file;
        char *buf;
        gsize len;

        file = g_file_new_for_path("/etc/passwd");
        g_file_load_contents(file, NULL, &buf, &len, NULL, NULL);

        fwrite(buf, len, 1, stdout);
        g_free(buf);

        return 0;
}

In Parameters

You pass your data to a function with Transfer full annotation, you are no longer the owner of the object.


/* -*- compile-command: "gcc -Wall -Wextra -g $(pkg-config --cflags --libs gio-2.0) transfer-full-in.c" -*- */
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
        void *buf;
        gsize len;
        GBytes *bytes;

        len = 100;
        buf = malloc(len);
        sprintf(buf, "%s", "hello");
        bytes = g_bytes_new_take(buf, len);

        // It might be a good idea to remove the reference
        // to the buf.  This ensures that we are no longer
        // able to free it by accident.
        buf = NULL;
        len = 0;

        fwrite(g_bytes_get_data(bytes, NULL),
               g_bytes_get_size(bytes),1, stdout);

        // buf will be freed when byts are freed
        g_bytes_unref(bytes);

        return 0;
}

No comments :