Re: The use of RefPtr



On Sat, 07 Mar 2009 16:32:18 -0700
Eddie Carle <eddie erctech org> wrote:
[snip]
> Now I see where the memory leak comes from. I was just examining the
> objectbase.h file in glibmm. This raises an interesting question as to
> why these functions are virtual. Were they made virtual to allow for
> differing allocation models? Let me see if I have this correct as far
> as deallocation of a tree model would go.
> 
>      1. TreeView/ComboBox is destroyed and associated TreeModels
> RefPtr calls unreference().
>      2. unreference() calls g_object_unref() on the underlying
>         dynamically allocated C GTK+ treemodel.
>      3. If the reference count of the C GTK+ treemodel reaches zero it
>         self destructs.
>      4. After self-destruction a callback is made to
>         destroy_notify_callback_()
>      5. This function then calls destroy_notify_() on the original
>         TreeModel C++ wrapper.
>      6. This function then calls a "delete this" to self destruct.
> 
> So it is in fact impossible to get the underlying C GTK+ object on the
> stack. Correct?

It is impossible to get the underlying C GTK+/glib object on the stack.
It is part of the GObject type system that all GObjects are created with
g_object_new(), overridden for the relevant type.

It would not be impossible (Gtk::Object enables it) to create the
Glib::Object wrapper (but only the wrapper) on the stack, but it is
ill-advised in a custom pure Glib::Object because it requires you to
fiddle with things which are not part of the public API for glibmm. It
is not impossible because at the C layer, the only differences between a
GObject and GtkObject are that (1) the former does not have a floating
reference but GtkObject does (it comes in fact from GInitiallyUnowned)
- which you can convert to a normal reference anyway with
g_object_ref_sink(), and (2) GtkObject has a destroy signal which will
cause all GTK+ containers to release their references to the object.

As I mentioned in my follow-up e-mail, to create a wrapper object
derived from Gtk::TreeModel on the stack (which is derived from
Glib::Object but not Gtk::Object) you would need to override
Glib::ObjectBase::destroy_notify_() so that it does not call 'delete
this' and also set the internal gobject pointer to NULL to neutralise
Glib::ObjectBase::~ObjectBase().  That should do it but you would need
to inspect the code to see that nothing else is required. However, for
the sake of avoiding allocating a pointer on free store it just does not
seems worthwhile to me, and you could easily become victim to changes
of internal implementation later.

I am not a gtkmm maintainer, but yes,
Glib::ObjectBase::destroy_notify_() is presumably virtual to permit a
different allocation strategy, as in the case of objects derived from
Gtk::Object, which can be auto (stack) objects. But even in the case of
Gtk::Objects, all the guts comprising the underlying C GTK+ object are
allocated on the heap.  That is not to say that it is not worth
creating auto Gtk::Object wrapper objects - it might very marginally
reduce heap fragmentation, but it is probably imperceptible.

That does not explain why Glib::Object and Gtk::Object are treated
differently - it does not seem to me that Glib::ObjectBase/Glib::Object
needed to be implemented this way, but they were.  It may possibly be a
hangover from glib-1 and gtk+-1.

Chris


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]