Разрушение 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
потому что он устарел, и я также не хочу работать с необработанным указателем, потому что тогда деструкторы должны вручную удалить указатели, что добавляет дополнительную сложность ...
мои вопросы:
- почему причины
Glib::RefPtr
это "критическое предупреждение" (возможно, двойной бесплатно)? - почему он работает с gtkmm 2.4, но не в 3.0?
- могу ли я исправить код с помощью
Glib::RefPtr
и gtkmm 3.0? - как я должен справляться с такими ситуациями в целом?
2 ответов
счетчик ссылок слишком низок, и вы можете исправить это, добавив ptr->reference()
после ptr->show_all()
. У меня есть объяснение, но возьмите его с солью:
- Glib:: RefPtr не увеличивает счетчик ссылок своего объекта изначально.
- GtkWindow будет иметь отсчет ссылки первоначально 1.
- когда ваше окно закрыто, библиотека уменьшает счетчик ссылок своего GtkWindow один раз.
- так как счетчик GtkWindow равен нулю, он уничтожен.
- комплект.run () видя, что больше нет окон, возвращается.
- w выходит из области видимости, и количество объектов RefPtr уменьшается, вызывая ошибку.
Я не могу ответить #2 или #4 К сожалению, так как эта область gtk/gtkmm все еще немного загадочна (для меня).
Glib:: RefPtr не предназначен для общего использования. Вы должны использовать его, когда API заставляет вас, но не иначе. GtkWindow (или Gtk::Window) имеет свое собственное нечетное управление памятью, которое на самом деле не совместимо с RefPtr.
Если вы хотите smartpointer общего назначения, попробуйте std::shared_ptr или std:: unique_ptr. Или вы можете найти что-то в boost.