Разрушение Glib:: RefPtr вызывает неудачные утверждения в ядре GTK 3

ребята из Gtkmm являются сравнение Glib::RefPtr С std::auto_ptr<>:

Glib::RefPtr - это smartpointer. В частности, это smartpointer для подсчета ссылок. Возможно, вы знакомы с std::auto_ptr<>, который также является smartpointer, но Glib::RefPtr<> намного проще и полезнее.

но по какой-то странной причине я не могу закончить свою работу с RefPtr. Тот же код просто отлично подходит для auto_ptr.

в следующий код SmartPtr является просто заполнителем для одного из этих двух smartpointers.

#include <gtkmm.h>
#include <iostream>
#include <tr1/memory>

struct WindowHolder {
  SmartPtr<Gtk::Window> ptr;

  WindowHolder()
    : ptr(new Gtk::Window)
  {
    ptr->signal_delete_event().connect(sigc::mem_fun(*this, &WindowHolder::reset));
    ptr->show_all();
  }

  bool reset(GdkEventAny* event)
  {
    Gtk::Main::quit();
  }
};

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);
  WindowHolder w;
  kit.run();
}

при компиляции, я сначала определим SmartPtr as Glib::RefPtr и затем std::auto_ptr.

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out 
(main:22093): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed
$ g++ '-DSmartPtr=std::auto_ptr' `pkg-config --cflags --libs gtkmm-3.0` main.cc && ./a.out 
$

проблема в том, что GLib-GObject-CRITICAL. В моем реальном приложении это не просто одна строка, а целая куча. Во второй версии с std::auto_ptr все разрушается хорошо.

достаточно странный код это просто отлично в GTK 2:

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-2.4` main.cc && ./a.out 
$

Я не хочу зависеть от std::auto_ptr потому что он устарел, и я также не хочу работать с необработанным указателем, потому что тогда деструкторы должны вручную удалить указатели, что добавляет дополнительную сложность ...

мои вопросы:

  1. почему причины Glib::RefPtr это "критическое предупреждение" (возможно, двойной бесплатно)?
  2. почему он работает с gtkmm 2.4, но не в 3.0?
  3. могу ли я исправить код с помощью Glib::RefPtr и gtkmm 3.0?
  4. как я должен справляться с такими ситуациями в целом?

2 ответов


счетчик ссылок слишком низок, и вы можете исправить это, добавив ptr->reference() после ptr->show_all(). У меня есть объяснение, но возьмите его с солью:

  • Glib:: RefPtr не увеличивает счетчик ссылок своего объекта изначально.
  • GtkWindow будет иметь отсчет ссылки первоначально 1.
  • когда ваше окно закрыто, библиотека уменьшает счетчик ссылок своего GtkWindow один раз.
  • так как счетчик GtkWindow равен нулю, он уничтожен.
  • комплект.run () видя, что больше нет окон, возвращается.
  • w выходит из области видимости, и количество объектов RefPtr уменьшается, вызывая ошибку.

Я не могу ответить #2 или #4 К сожалению, так как эта область gtk/gtkmm все еще немного загадочна (для меня).

ссылка:http://www.gtkforums.com/viewtopic.php?t=2412


Glib:: RefPtr не предназначен для общего использования. Вы должны использовать его, когда API заставляет вас, но не иначе. GtkWindow (или Gtk::Window) имеет свое собственное нечетное управление памятью, которое на самом деле не совместимо с RefPtr.

Если вы хотите smartpointer общего назначения, попробуйте std::shared_ptr или std:: unique_ptr. Или вы можете найти что-то в boost.