[Gtk-sharp-list] refcounting, GC, and glade.. (patch, need review)

Vladimir Vukicevic vladimir@pobox.com
13 Oct 2002 16:04:03 -0700

Hmm.  I just had a discussion with owen where he gave me a crash-course
in glib/gtk memory management.  It looks to me we're doing a few things
wrong.  Currently, every gobject that we get back we unref() when it's
finalized in C#.  This I'm pretty sure is the wrong behaviour.  From
talking to him, it looks like the following needs to happen:

- We need to either:
  - Ref every object we get back, and create a separate C# wrapper every
time, even if the underlying Handle will be the same.  This seems the
easiest and least error-prone thing to do.
  - Ref only the first time we see a particular object pointer, and
store the C# object - return the same c# object for the same glib
object.  This would be doable, but tricky to get right -- by storing
those objects in the hashtable, they'll never get c# finalized, hence
never gobject unref'd.

- For Gtk.Object derivatives:
  - We need to ref and sink the objects in the constructors.  Right now
he floating object behaviour is fairly broken; it's only not causing too
many problems for small things because every widget that gets added to a
container is sunk by that container -- this also means that we never own
the reference to this widget in c#, and the underlying handle could
become invalid at any time.  Small code snippet that shows this problem:

  public class Driver {
    public static void Main () {
      Gtk.Application.Init ();
      using (Gtk.Widget w = new Gtk.Label ("foo")) {

This will spam a warning to stderr about finalizing a floating object,
since noone has officially taken ownership of this object.

The only solution to the sinking problem that I can think of is to
modify the generator so that it does the right thing in every object's
constructors that are a derivative of Gtk.Object -- namely,
   Raw = gtk_foo_new (...)
   Ref ();
   Sink ();
instead of just assigning to Raw as they do now.  All objects that are
returned by get_* or whatever functions should come unreffed -- in this
case we need to Ref() and create a C# wrapper.

I think this should get us most of the way towards correct object
management; I'm going to try implementing this tonight and see where I
end up.

	- Vlad

Vladimir Vukicevic <vladimir@pobox.com>