Re: Deleting widgets loaded using libglademm



Am Dienstag, den 09.01.2007, 21:25 +0100 schrieb Tomasz Olszewski:
> Hello!
> 
> gtkmm documentation seems a bit confusing when it comes to libglademm.
> Chapter 23
> (http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/ch23.html) says
> that:
> 
> "The widgets are owned by the |Gnome::Glade::Xml| instance, and will be
> deleted automatically when it is deleted, when the last copy of the
> smartpointer goes out of scope."

The documentation is blatantly wrong, or at the very least highly
misleading.  The RefPtr<Gnome::Glade::Xml> smart pointer only controls
the in-memory representation of the xml tree, and has nothing to do with
the lifetime of the widgets as far as I can tell.  In fact, it's a waste
of memory not to let that smart pointer go out of scope right after
retrieving all the widget pointers.

> For me this means that I don't have to worry about widget deletion
> because it will be done automatically. Great, no risk of memory leak!

Despite what I said above, that is almost true.  See below.

> Let's read on. On the next page there is a paragraph that confused me a
> lot. Let me quote it here:
> 
> |"get_widget()| returns child widgets that are |manage()|ed (see the
> Memory Management
> <http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/ch22.html>
> chapter), so they will be deleted when their parent container is
> deleted. So, if you get only a child widget from libglademm, instead of
> a whole window, then you must either put it in a |Container| or delete
> it. |Windows| (such as |Dialogs|) can not be managed because they have
> no parent container, so you must delete them at some point."

That is correct.

> Basically it says that only child widgets will be deleted automatically
> because their lifetime is managed by their parents. All other widgets
> *must* be deleted by hand.

Right, but "all other widgets" = only windows.  You'll typically have
very few windows but an awful lot of widgets.  Also note that each
widget will already be a child of its parent container after loading the
glade file (not counting toplevel windows as widgets).  Well, at least I
don't think glade lets you create orphaned widgets; it might be
different though if you write the xml file manually.

I have to admit I don't know what happens if you don't retrieve the
toplevel window at all, as I never tried that.  It might turn out that
for this special case the statement you quoted at the top is actually
true.  But that would, in my opinion, constitute an abuse of the
Glib::RefPtr<Gnome::Glade::Xml> instance, and be a waste of memory.

> What happened to the Gnome::Glade::Xml
> smartpointer then? Wasn't it supposed to perform such deletion when
> being destroyed? Perhaps I should understand this part of the
> documentation as: "You *can* delete widgets loaded with libglademm by
> yourself, but if you won't, no memory leaks will appear, because the Xml
> smartpointer eventually takes care of any pending deletion. What is
> more, if you do delete a widget by hand, there is no double deletion
> risk"? What's the correct interpretation?

1. Let the Glib::RefPtr<Gnome::Glade::Xml> go out of scope as soon as
possible after retrieval of the widget pointers you need.

2. Container ownership has already been taken care of.  Deleting a
widget owned by some container is possible and will cause removal from
the parent container if everything goes right.  You'll rarely want to do
that, though, unless you have some really special needs.

3. You have to take care of deleting toplevel windows yourself.  But you
could use e.g. std::auto_ptr<> for that purpose (it's a simple ownership
transferring smart pointer and just right for a situation like this).

For a real-life example of this stuff you could look at the regexxer
source code:

http://svn.gnome.org/viewcvs/regexxer/trunk/src/mainwindow.cc?view=markup
http://svn.gnome.org/viewcvs/regexxer/trunk/src/mainwindow.h?view=markup

In particular, you'll want to look at MainWindow::load_xml() and
MainWindow::on_about().

Hope this helps,
--Daniel





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