2012-04-14 14 views
7

Los chicos de Gtkmm son comparingGlib::RefPtr con std::auto_ptr<>:Destructing Glib :: RefPtr hace que las afirmaciones no en el núcleo GTK 3

Glib::RefPtr es una SmartPointer. Específicamente, es un smartpointer de recuento de referencias. Es posible que esté familiarizado con std::auto_ptr<>, que también es un smartpointer, pero Glib::RefPtr<> es mucho más simple y más útil.

Pero por alguna extraña razón, no puedo hacer mi trabajo con el RefPtr. El mismo código está bien con un auto_ptr.

En el siguiente código, SmartPtr es solo un marcador de posición para uno de estos dos smartpointers.

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

Al compilar, primero defino como SmartPtrGlib::RefPtr y luego como 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 
$ 

El problema es GLib-GObject-CRITICAL. En mi aplicación real, esta no es solo una línea, sino un montón de ellas. En la segunda versión con std::auto_ptr todo se destruye bien.

lo suficientemente extraño el código es muy bien en GTK 2:

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

no quiero depender de std::auto_ptr porque es obsoleto y que también no quieren trabajar con un puntero prima porque a continuación, los destructores tienen que eliminar manualmente los punteros que añade complejidad adicional ...

Mis preguntas son:

  1. Por qué provoca esta Glib::RefPtr "Crítica l advertencia "(probablemente un doble gratis)?
  2. ¿Por qué funciona con gtkmm 2.4 pero no en 3.0?
  3. ¿Puedo arreglar el código con Glib::RefPtr y gtkmm 3.0?
  4. ¿Cómo debo manejar tales situaciones en general?

Respuesta

4

El recuento de referencia es demasiado baja, y se puede solucionar mediante la adición de un ptr->reference() después ptr->show_all(). Tengo una explicación, pero tómelo con un grano de sal:

  • Glib :: RefPtr no incrementa inicialmente el recuento de referencias de su objeto.
  • El GtkWindow tendrá inicialmente un recuento de referencia de 1.
  • Cuando su ventana está cerrada, la biblioteca reduce el recuento de referencias de su GtkWindow una vez.
  • Dado que el recuento de GtkWindow es cero, se destruye.
  • kit.run() viendo que no hay más ventanas, vuelve.
  • w sale del alcance y el recuento de objetos del RefPtr se reduce causando el error.

Desafortunadamente no puedo responder al # 2 o al # 4, ya que esta área de gtk/gtkmm todavía es un poco misteriosa (para mí).

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

5

Glib :: RefPtr no está destinado a ser para uso general. Debería usarlo cuando la API lo obligue a hacerlo, pero no de otra manera. GtkWindow (o Gtk :: Window) tiene su propia gestión de memoria impar que no es realmente compatible con RefPtr.

Si desea un smartpointer de propósito general, intente con std :: shared_ptr o std :: unique_ptr. O podrías encontrar algo en potencia.

+0

Gracias por aclarar eso. – glitto

+0

¿'Glib :: RefPtr' no utiliza el recuento de referencias interno' GObject'? –

+0

@ el.pescado [Revise la documentación] (https://developer.gnome.org/glibmm/stable/classGlib_1_1RefPtr.html#details): "_RefPtr <> puede almacenar cualquier clase que tenga métodos de referencia() y unreference() y cuyo destructor es noexcept (el predeterminado para los destructores). En gtkmm, eso es cualquier cosa derivada de Glib :: ObjectBase, como Gdk :: Pixmap._ "Entonces, sí. Es un puntero inteligente intrusivo destinado solo para 'GObject's envuelto, aprovechando su recuento de referencia preexistente. En lugar de envolver el propio 'GObject's con él, me da la impresión de que es solo un detalle de implementación de las bibliotecas' mm'. –

Cuestiones relacionadas