Object Destruction

Again, it is often difficult to figure out which mechanism to use to hook into the object's destruction process: when the last g_object_unref function call is made, a lot of things happen as described in Table 5, “g_object_unref”.

The destruction process of your object might be split in two different phases: dispose and the finalize.

#define MAMAN_BAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MAMAN_TYPE_BAR, MamanBarPrivate))

struct _MamanBarPrivate
{
  GObject *an_object;

  gchar *a_string;
};

G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT);

static void
maman_bar_dispose (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);

  /* 
   * In dispose, you are supposed to free all types referenced from this
   * object which might themselves hold a reference to self. Generally,
   * the most simple solution is to unref all members on which you own a 
   * reference.
   */

  /* dispose might be called multiple times, so we must guard against
   * calling g_object_unref() on an invalid GObject.
   */
  if (self->priv->an_object)
    {
      g_object_unref (self->priv->an_object);

      self->priv->an_object = NULL;
    }

  /* Chain up to the parent class */
  G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject);
}

static void
maman_bar_finalize (GObject *gobject)
{
  MamanBar *self = MAMAN_BAR (gobject);

  g_free (self->priv->a_string);

  /* Chain up to the parent class */
  G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject);
}

static void
maman_bar_class_init (MamanBarClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->dispose = maman_bar_dispose;
  gobject_class->finalize = maman_bar_finalize;

  g_type_class_add_private (klass, sizeof (MamanBarPrivate));
}

static void
maman_bar_init (MamanBar *self);
{
  self->priv = MAMAN_BAR_GET_PRIVATE (self);

  self->priv->an_object = g_object_new (MAMAN_TYPE_BAZ, NULL);
  self->priv->a_string = g_strdup ("Maman");
}

Add similar code to your GObject, make sure the code still builds and runs: dispose and finalize must be called during the last unref.

It is possible that object methods might be invoked after dispose is run and before finalize runs. GObject does not consider this to be a program error: you must gracefully detect this and neither crash nor warn the user.