2012-04-14 41 views
7

從gtkmm的該人是comparingGlib::RefPtrstd::auto_ptr<>解構油嘴:: RefPtr導致失敗的斷言在GTK 3芯

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「CRITICA l警告「(可能是雙倍免費)?
  2. 爲什麼它在gtkmm 2.4下工作,但不在3.0下?
  3. 我可以使用Glib::RefPtr和gtkmm 3.0修復代碼嗎?
  4. 我應該如何處理這種情況?

回答

4

引用計數過低,您可以通過ptr->show_all()後加入ptr->reference()修復它。我有一個解釋,但採取與一粒鹽:

  • 油嘴:: RefPtr最初不增加它的對象的引用計數。
  • GtkWindow的初始參考計數爲1.
  • 當窗口關閉時,庫會將其GtkWindow的引用計數遞減一次。
  • 由於GtkWindow的計數爲零,因此它被銷燬。
  • kit.run()看到沒有更多的窗口,返回。
  • w超出範圍並且RefPtr的對象計數遞減導致錯誤。

不幸的是,我不能真正回答#2或#4,因爲gtk/gtkmm的這個區域仍然有點神祕(對我來說)。

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

5

油嘴:: RefPtr並不意味着是用於一般用途。您應該在API強制您使用它時使用它,但不能以其他方式使用它。 GtkWindow(或Gtk :: Window)有其自己奇怪的內存管理,它不與RefPtr真正兼容。

如果你想要一個通用智能指針,試試std :: shared_ptr或std :: unique_ptr。或者你可以找到一些提升。

+0

感謝您澄清。 – glitto 2012-04-23 20:56:33

+0

'Glib :: RefPtr'不使用內部'GObject'引用計數嗎? – 2016-07-08 07:21:28

+0

@ el.pescado [檢查文檔](https://developer.gnome.org/glibmm/stable/classGlib_1_1RefPtr.html#details):「_RefPtr <>可以存儲任何具有reference()和unreference()方法的類,並且其析構函數是noexcept(析構函數的默認值)。在gtkmm中,這是從Glib :: ObjectBase派生的任何東西,比如Gdk :: Pixmap._「所以,是的。這是一個只能用於包裝'GObject'的插入式智能指針,利用其現有的引用計數。而不是用它包裝自己的'GObject's,我覺得它只是'mm'庫的實現細節。 – 2016-08-13 19:05:56