Справочное описание GObject |
---|
Опять, часто сложно выяснить какой механизм использовать для обработки процесса уничтожения объекта:
когда сделан последний вызов функции
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;
}