2012-04-14 15 views
7

Các chàng trai đến từ gtkmm là comparingGlib::RefPtr với std::auto_ptr<>:huỷ Glib :: RefPtr gây thất bại khẳng định trong lõi GTK 3

Glib::RefPtr là một smartpointer. Cụ thể, nó là một smartpointer đếm tham chiếu. Bạn có thể quen thuộc với std::auto_ptr<>, cũng là một con trỏ thông minh, nhưng Glib::RefPtr<> đơn giản hơn nhiều và hữu ích hơn.

Nhưng vì một lý do lạ, tôi không thể hoàn thành công việc của mình với RefPtr. Cùng một mã là tốt với một auto_ptr.

Trong mã sau, SmartPtr chỉ là trình giữ chỗ cho một trong hai trình thông minh này.

#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(); 
} 

Khi biên dịch, tôi lần đầu tiên xác định SmartPtr như Glib::RefPtr và sau đó là 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 
$ 

Vấn đề là GLib-GObject-CRITICAL. Trong ứng dụng thực sự của tôi, đây không chỉ là một dòng duy nhất mà là cả một nhóm. Trong phiên bản thứ hai với std::auto_ptr mọi thứ đều bị phá hủy tốt.

đủ Strange mã nó chỉ là tốt trong GTK 2:

$ g++ '-DSmartPtr=Glib::RefPtr' `pkg-config --cflags --libs gtkmm-2.4` main.cc && ./a.out 
$ 

Tôi không muốn phụ thuộc vào std::auto_ptr vì nó bị phản đối và tôi cũng không muốn làm việc với một con trỏ thô vì thì hàm hủy phải tự xóa các con trỏ mà thêm thêm phức tạp ...

câu hỏi của tôi là:

  1. Tại sao gây Glib::RefPtr này "critica l cảnh báo "(có thể là một đôi miễn phí)?
  2. Tại sao nó hoạt động với gtkmm 2.4 nhưng không hoạt động ở 3.0?
  3. Tôi có thể sửa mã bằng Glib::RefPtr và gtkmm 3.0 không?
  4. Tôi nên xử lý các tình huống như vậy nói chung như thế nào?

Trả lời

4

Số tham chiếu quá thấp và bạn có thể khắc phục bằng cách thêm ptr->reference() sau ptr->show_all(). Tôi có một lời giải thích, nhưng lấy nó bằng một hạt muối:

  • Glib :: RefPtr không tăng số lượng tham chiếu của đối tượng ban đầu.
  • GtkWindow sẽ có số tham chiếu ban đầu là 1.
  • Khi cửa sổ của bạn bị đóng, thư viện sẽ giảm số lượng tham chiếu của GtkWindow một lần.
  • Vì số GtkWindow là 0, nó bị hủy.
  • kit.run() thấy không còn cửa sổ, trả lại.
  • w nằm ngoài phạm vi và số lượng đối tượng của RefPtr bị giảm đi gây ra lỗi.

Tôi thực sự không thể trả lời # 2 hoặC# 4, vì khu vực này của gtk/gtkmm vẫn còn hơi bí ẩn (đối với tôi).

Tham chiếu: http://www.gtkforums.com/viewtopic.php?t=2412

5

Glib :: RefPtr không có nghĩa là để sử dụng chung. Bạn nên sử dụng nó khi API buộc bạn, nhưng không phải khác. GtkWindow (hoặc Gtk :: Window) có quản lý bộ nhớ riêng lẻ mà không thực sự tương thích với RefPtr.

Nếu bạn muốn có một con trỏ thông minh mục đích chung, hãy thử std :: shared_ptr hoặc std :: unique_ptr. Hoặc bạn có thể tìm thấy một cái gì đó trong tăng.

+0

Cảm ơn bạn đã làm rõ điều đó. – glitto

+0

Không 'Glib :: RefPtr' sử dụng số tham chiếu nội bộ' GObject'? –

+0

@ el.pescado [Kiểm tra tài liệu] (https://developer.gnome.org/glibmm/stable/classGlib_1_1RefPtr.html#details): "_RefPtr <> có thể lưu trữ bất kỳ lớp nào có phương thức reference() và unreference() , và có destructor là noexcept (mặc định cho destructors) Trong gtkmm, đó là bất cứ điều gì có nguồn gốc từ Glib :: ObjectBase, chẳng hạn như Gdk :: Pixmap._ "Vì vậy, có. Đó là một con trỏ thông minh xâm nhập chỉ dành cho gói 'GObject', tận dụng số đếm tham chiếu đã tồn tại từ trước của chúng. Thay vì gói riêng 'GObject' với nó, tôi có ấn tượng rằng nó chỉ là một chi tiết thực hiện của các thư viện 'mm'. –

Các vấn đề liên quan