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

时间:2012-04-14 19:17:23

标签: c++ memory-management gtk gtkmm gtk3

来自Gtkmm的人comparing Glib::RefPtr std::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();
}

编译时,我首先将SmartPtr定义为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 个答案:

答案 0 :(得分:5)

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

如果您需要通用智能指针,请尝试使用std :: shared_ptr或std :: unique_ptr。或者你可以在boost中找到一些东西。

答案 1 :(得分:4)

引用计数太低,您可以在ptr->reference()之后添加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