破坏Glib :: RefPtr导致GTK 3核心中的断言失败

gli*_*tto 7 c++ gtk memory-management gtkmm gtk3

从gtkmm的这些家伙都比较 Glib::RefPtrstd::auto_ptr<>:

Glib::RefPtr是一个智能指针.具体来说,它是一个参考计数智能指针.您可能熟悉std::auto_ptr<>,这也是一个智能指针,但Glib::RefPtr<>更简单,更有用.

但由于一些奇怪的原因,我无法完成我的工作RefPtr.相同的代码就好了auto_ptr.

在下面的代码中,SmartPtr只是这两个智能指针之一的占位符.

#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();
}
Run Code Online (Sandbox Code Playgroud)

在编译时,我首先定义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 
$
Run Code Online (Sandbox Code Playgroud)

问题是这个GLib-GObject-CRITICAL.在我的实际应用中,这不仅仅是一行,而是一大堆.在第二个版本中,std::auto_ptr一切都被破坏了.

奇怪的是,在GTK 2中它的代码很好:

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-2.4` main.cc && ./a.out 
$
Run Code Online (Sandbox Code Playgroud)

我不想依赖std::auto_ptr它,因为它已被弃用,我也不想使用原始指针,因为析构函数必须手动删除指针,这增加了额外的复杂性......

我的问题是:

  1. 为什么导致Glib::RefPtr这种"严重警告"(可能是双重免费)?
  2. 为什么它适用于gtkmm 2.4而不是3.0?
  3. 我可以用Glib::RefPtr和gtkmm 3.0 修复代码吗?
  4. 一般来说我该如何处理这种情况?

mur*_*ayc 5

Glib :: RefPtr不适用于一般用途.你应该在API强制要求时使用它,但不是这样.GtkWindow(或Gtk :: Window)有自己的奇数内存管理,它与RefPtr并不真正兼容.

如果你想要一个通用的smartpointer,试试std :: shared_ptr或std :: unique_ptr.或者你可以找到一些提升的东西.


erg*_*sys 4

引用计数太低,可以通过添加ptr->reference()after来修复ptr->show_all()。我有一个解释,但请持保留态度:

  • Glib::RefPtr 最初不会增加其对象的引用计数。
  • GtkWindow 的引用计数最初为 1。
  • 当您的窗口关闭时,库会减少其 GtkWindow 的引用计数一次。
  • 由于 GtkWindow 的计数为零,因此它被销毁。
  • kit.run() 看到没有更多窗口,返回。
  • w 超出范围,并且 RefPtr 对象的计数递减,从而导致错误。

不幸的是,我无法真正回答#2 或#4,因为 gtk/gtkmm 的这个领域(对我来说)仍然有点神秘。

参考: http: //www.gtkforums.com/viewtopic.php ?t=2412