Re: Can I use gtk_widget_unref() to releasetthe object created by gtk_invisible_new()?



Hi,

Answers to your questions:

1) Yes, the GtkInvisible is *not* floating (see the my description 
   earlier in this thread to find out why). Note that any toplevel
   widget (GtkWindow, GtkDialog) is *not floating* either, for the same reason.

2) Yes, you need to use gtk_widget_destroy in this case, not g_object_unref.
   (the reason is mentioned earlier in this thread).
   
The floating references in GTK make the whole reference counting a bit messy.
The following points make life easier:

 *  Always have a matching g_object_unref for each g_object_ref you have

 *  Always have a g_object_unref for each function that returns new GObject
    that *doesn't use* floating references (GtkTreeModels, GtkSizeGroups)

 *  When creating new objects that *may be floating* (all GtkWidget based
    ones, GtkInvisible being one example), don't try to use g_object_unref 
    (if not adding extra reference trough g_object_ref earlier). Pack them
    to containers and use gtk_widget_destroy when you are done 
    with them. Usually you need to use g_object_ref/unref with widgets 
    only if you are implementing a custom container.

Hope this helps,

-Markku-

Lainaus Brian Lu Sun COM:

> Hi, Markku,
> 
> Thanks a lot for your help.
> 
> I did some further investigation on this issue.  I have two questions on 
> this issue:
> 
> 1. The object created by gtk_invisible_new() is not "floating". 
> 
> Here is a snippet from gtk+-2.12.5/tests/testselection.c
> 
>  init_atoms();
>   selection_widget = gtk_invisible_new ();
> *  m = GTK_OBJECT_FLOATING(selection_widget);  //***
>   dialog = gtk_dialog_new ();
>   gtk_widget_set_name (dialog, "Test Input");
> 
> The black line (marked with "**") is added by me.
> When I run testselection, "m" is set to 0 instead of 1.  Which means the 
> selection_widget is not "floating".
> right or I used a wrong macro?
> 
> 2. How to release an object created by gtk_invisible_new()?
> Look at following snippets:
> 
>    void InitWidget() {
>         mWidget = gtk_invisible_new();
>         *gtk_object_ref(GTK_OBJECT(mWidget)); //***
>         gtk_object_sink(GTK_OBJECT(mWidget));
>         gtk_widget_ensure_style(mWidget);
>         mStyle = gtk_widget_get_style(mWidget);
>     }
> 
>    nsLookAndFeel::~nsLookAndFeel()
>    {
>        //  gtk_widget_destroy(mWidget);
>        gtk_widget_unref(mWidget);
>    }
> 
> If I comment out the black line (marked with "**"), the mWidget 
> reference count is 1 as expected,
> but when unref  it in nsLookAndFeel::~nsLookAndFeel,  thunderbird will 
> crash.
> It looks like that I can't us gtk_widget_unref() on the object returned 
> by gkt_invisible_new().
> 
> So my question is how to "free" an object returned by gtk_invisible_new()?
> 
> Thanks a lot
> 
> Brian
> 
> 
> Markku Vire wrote:
> > Hi,
> >
> > The reference that is returned by gtk_invisible_new is not owned by the
> > caller. If one tries to unref it, it's an immediate memory corruption.
> >
> > When a toplevel widget is concerned, the things go like the following:
> >  * New floating GtkWidget is created (not owned by anyone).
> >  * GTK library takes ownership of the toplevel (calling
> >    g_object_ref_sink). Floating reference is converted to normal one.
> >  * Widget pointer is returned (refcount = 1, owner = gtk).
> >
> > So, in the code you attached gtk_object_ref increases the reference
> > count to 2, gtk_object_sink does nothing (since it not floating any
> > more).
> >
> > Later gtk_widget_unref decreases refcount back to 1, but there is still
> > one reference left (owned by gtk). Trying to remove it by g_object_unref
> > is a bug (as you noticed). The way to ask GTK to release the last
> > reference is to call gtk_widget_destroy.
> >
> > If you are just interested about the GtkStyle object, you could try
> > using gtk_rc_get_style_by_paths for example? 
> >
> > Cheers,
> >
> > -Markku-
> >
> > On Fri, 2008-01-11 at 16:53 +0800, Brian Lu wrote:
> >   
> >> Thanks a lot for your explanation.  But look at following snippet from 
> >> firefox latest code base:
> >>     void InitWidget() {
> >>         mWidget = gtk_invisible_new();
> >>         gtk_object_ref(GTK_OBJECT(mWidget));
> >>         gtk_object_sink(GTK_OBJECT(mWidget));
> >>         gtk_widget_ensure_style(mWidget);
> >>         mStyle = gtk_widget_get_style(mWidget);
> >>     }
> >> see 
> >>
> http://lxr.mozilla.org/seamonkey/source/widget/src/gtk2/nsLookAndFeel.h#77
> >> and
> >> nsLookAndFeel::~nsLookAndFeel()
> >> {
> >>     //  gtk_widget_destroy(mWidget);
> >>     gtk_widget_unref(mWidget);
> >> }
> >> see 
> >>
> http://lxr.mozilla.org/seamonkey/source/widget/src/gtk2/nsLookAndFeel.cpp#78
> >>
> >> I find mWidget is leaked (detected by using libumem.so provided by
> solaris).
> >>
> >> I don't understand why calling gtk_object_ref() to increase mWidget 
> >> reference count. 
> >> This causes mWidget's reference count to be 2 and gtk_widget_unref() in 
> >> deconstructor decreases it to 1.
> >>
> >> Thanks
> >>
> >> Brian
> >>
> >>
> >>
> >> Markku Vire wrote:
> >>     
> >>> Hi,
> >>>
> >>> The caller doesn't own the returned reference in case of any gtk_*_new
> >>> functions, but the results are floating references (they are removed
> >>> once somebody calls gtk_object_sink). This is different from normal
> >>> GObjects. So, unreffing the returned value causes practically a double
> >>> free.
> >>>
> >>> gtk_widget_destroy in turn runs dispose, ie. asks widget to drop
> >>> references to other widgets. Dropping external references usually
> causes
> >>> somebody else to drop the last reference to your widget, so it
> >>> efectively gets destroyed. In case of toplevels some global window list
> >>> is holding the reference.
> >>>
> >>> Calling gtk_widget_destroy without taking ownership a a widget is
> >>> usually a bug that causes a memory leak, but this is not the case here,
> >>> since we are talking about a toplevel.
> >>>
> >>> Cheers,
> >>>
> >>> -Markku- 
> >>>
> >>> On Wed, 2008-01-09 at 17:39 +0800, Brian Lu wrote:
> >>>   
> >>>       
> >>>> Hi, experts,
> >>>>
> >>>> I found following codes will crash in gnome 2.21 environment:
> >>>>
> >>>>   ...
> >>>>   GtkWidget *foo = gtk_invisible_new();
> >>>>   gtk_widget_unref(foo);
> >>>>   ...
> >>>>
> >>>> But it works well if gtk_widget_unref() is replaced with 
> >>>> gtk_widget_destroy().
> >>>>
> >>>> Does that mean that we can't use gtk_widget_unref() on such object and
> 
> >>>> we can only
> >>>> use gtk_widget_destroy() to release it?
> >>>>
> >>>> Thanks
> >>>>
> >>>> Brian
> >>>> _______________________________________________
> >>>> gtk-devel-list mailing list
> >>>> gtk-devel-list gnome org
> >>>> http://mail.gnome.org/mailman/listinfo/gtk-devel-list
> >>>>     
> >>>>         
> >>>   
> >>>       
> >> _______________________________________________
> >> gtk-devel-list mailing list
> >> gtk-devel-list gnome org
> >> http://mail.gnome.org/mailman/listinfo/gtk-devel-list
> >>     
> >
> >   
> 
> 




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