Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 破坏Glib::RefPtr会导致GTK 3核心中的断言失败_C++_Memory Management_Gtk_Gtkmm_Gtk3 - Fatal编程技术网

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

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

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 && ./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
,因为它已被弃用,我也不想使用原始指针,因为析构函数必须手动删除指针,这会增加额外的复杂性

我的问题是:

  • 为什么会导致此“严重警告”(可能是双重免费)
  • 为什么它与gtkmm 2.4兼容,而与3.0兼容
  • 我可以用Glib::RefPtr和gtkmm 3.0修复代码吗
  • 一般来说,我应该如何处理这种情况

  • 引用计数太低,您可以通过在
    ptr->show_all()
    之后添加
    ptr->reference()
    来修复它。我有一个解释,但请恕我直言:

    • Glib::RefPtr最初不会增加其对象的引用计数
    • GtkWindow最初的引用计数为1
    • 关闭窗口时,库将其GtkWindow的引用计数递减一次
    • 由于GtkWindow的计数为零,它将被销毁
    • 如果看到没有更多的窗口,则返回
    • w超出范围,并且RefPtr对象的计数减少,从而导致错误
    不幸的是,我真的无法回答2或4,因为gtk/gtkmm的这个领域(对我来说)仍然有点神秘


    参考资料:

    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
    库的一个实现细节。