C++ 破坏Glib::RefPtr会导致GTK 3核心中的断言失败
Gtkmm的伙计们是有着C++ 破坏Glib::RefPtr会导致GTK 3核心中的断言失败,c++,memory-management,gtk,gtkmm,gtk3,C++,Memory Management,Gtk,Gtkmm,Gtk3,Gtkmm的伙计们是有着std::auto_ptr的Glib::RefPtr: Glib::RefPtr是一个智能指针。具体来说,它是一个引用计数智能指针。您可能熟悉std::auto_ptr,它也是一个智能指针,但是Glib::RefPtr更简单、更有用 但由于某种奇怪的原因,我无法使用RefPtr完成我的工作。同样的代码可以通过自动执行 $ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-3.0` main.cc
std::auto_ptr
的Glib::RefPtr
:
Glib::RefPtr
是一个智能指针。具体来说,它是一个引用计数智能指针。您可能熟悉std::auto_ptr
,它也是一个智能指针,但是Glib::RefPtr
更简单、更有用
但由于某种奇怪的原因,我无法使用RefPtr
完成我的工作。同样的代码可以通过自动执行
$ 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
$
在下面的代码中,SmartPtr
只是这两个SmartPointer之一的占位符
#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();
}
问题在于这一点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
,因为它已被弃用,我也不想使用原始指针,因为析构函数必须手动删除指针,这会增加额外的复杂性
我的问题是:
引用计数太低,您可以通过在
ptr->show_all()
之后添加ptr->reference()
来修复它。我有一个解释,但请恕我直言:
- Glib::RefPtr最初不会增加其对象的引用计数
- GtkWindow最初的引用计数为1
- 关闭窗口时,库将其GtkWindow的引用计数递减一次李>
- 由于GtkWindow的计数为零,它将被销毁李>
- 如果看到没有更多的窗口,则返回李>
- w超出范围,并且RefPtr对象的计数减少,从而导致错误李>
参考资料:Glib::RefPtr不适用于一般用途。当API强制您使用时,您应该使用它,而不是其他情况。GtkWindow(或Gtk::Window)有自己的奇数内存管理,它与RefPtr不兼容
如果需要通用智能指针,请尝试std::shared\u ptr或std::unique\u ptr。或者你可以在boost中找到一些东西。不使用内部的
GObject
reference count?@el.pescado:“RefPtr可以存储任何具有reference()和unreference()方法的类,其析构函数是noexcept(析构函数的默认值)。在gtkmm中,这是从Glib::ObjectBase派生的任何内容,例如Gdk::Pixmap。它是一种侵入式智能指针,仅用于包装的GObject
s,利用其预先存在的引用计数。与其用它包装自己的GObject
s,我得到的印象是它只是mm
库的一个实现细节。