Уничтожение объекта

Опять, часто сложно выяснить какой механизм использовать для обработки процесса уничтожения объекта: когда сделан последний вызов функции g_object_unref, многое происходит как описано в Table 5, “g_object_unref”.

Процессс уничтожения вашего объекта должен быть разбит на две фазы: вы должны отменить и методы распределения и методы финализации класса.

struct _MamanBarPrivate { gboolean dispose_has_run; }; static GObjectClass parent_class = NULL; static void bar_dispose (GObject *obj) { MamanBar *self = (MamanBar *)obj; if (self->priv->dispose_has_run) { /* если распределение уже выполнено, возвращаемся. */ return; } /* убеждаемся что распределение не выполняется дважды. */ object->priv->dispose_has_run = TRUE; /* * В распределении, вы должны освободить все типы ссылок из этого объекта * которые могут сами содержать ссылки на себя. В основном, * самое простое решение освободить ссылки всех членов которыми вы * владеете. */ /* Формируем цепочку до родительского класса */ G_OBJECT_CLASS (parent_class)->dispose (obj); } static void bar_finalize (GObject *obj) { MamanBar *self = (MamanBar *)obj; /* Формируем цепочку до родительского класса */ G_OBJECT_CLASS (parent_class)->finalize (obj); } static void bar_class_init (BarClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = bar_dispose; gobject_class->finalize = bar_finalize; parent_class = g_type_class_peek_parent (klass); g_type_class_add_private(klass,sizeof(MamanBarPrivate)); } static void maman_bar_init (GTypeInstance *instance, gpointer g_class) { MamanBar *self = (MamanBar *)instance; self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, BT_TYPE_PATTERN, BtPatternPrivate); self->priv->dispose_has_run = FALSE; }

Добавьте подобный код в ваш GObject, убедитесь что код собирается и выполняется: распределение и финализация должны быть вызваны в течение последнего освобождения ссылки. Возможно что методы объекта могут быть вызваны после выполнения распределения и перед выполнением финализации. GObject не предполагает что это ошибка программы: вы должны изящно обнаружить это и не предупреждая пользователя не допустить краха. Для этого, вам потребуется следующий код в начале каждого объектного метода, чтобы убедиться что объектные данные остаются доступными перед манипулированием ими:

if (self->private->dispose_has_run) { /* Распределение было выполнено. Данные больше недоступны. */ return; }