Re: gtk_object_unref



On Tue, 2001-10-02 at 02:01, Jean-Christophe Berthon wrote:
> Hello everyone,
> 
> I'm trying to use the gtk_object_ref and gtk_object_unref function.
> 
> I have objects which are referencing shared points.
> Let say an object called A reference the point P. If P was not already
> created, I'm creating it.
> Then I add another object B which reference P also. As P is already created,
> I using gtk_object_ref on P.
> 
> If I remove B then I unref P and if I remove A, I again unref P but I want
> him to be destroy. It is working but I get an unnicely warning message in my
> xterm saying that :
> Gtk-CRITICAL **: file gtkobject.c: line 1179 (gtk_object_unref): assertion
> `object->ref_count > 0' failed.
> 
> 
> So I went looking at the source code of gtk_object_unref and I found this
> piece code :
> void gtk_object_unref (GtkObject *object)
> {
>   g_return_if_fail (object != NULL);
>   g_return_if_fail (GTK_IS_OBJECT (object));
>   g_return_if_fail (object->ref_count > 0);
> 
>   if (object->ref_count == 1)
>     {
>       gtk_object_destroy (object);
> 
>       g_return_if_fail (object->ref_count > 0);
>     }
> 
>   object->ref_count -= 1;
> 
>   if (object->ref_count == 0)
>     {
>       object->klass->finalize (object);
>     }
> }
> 
> So when unref is called and there was only one last reference on the object,
> destroy is called. As destroy doesn't decremente ref_count it should be
> fine, but it seems not to work as I've done a printf of object->ref_count
> before calling unref and I got 1 before calling gtk_object_unref and 0
> after...

what you are not seeing is the inner workings of gtk_object_destroy,
which is a virtual function, that in this case in fact decrements the
ref-counter (otherwise you wouldn't get the return_if_fail message). A
window, for example, will in its destroy function call
gtk_container_unregister_toplevel, which contains a gtk_widget_unref
call, so destroying a window using unref will give you the warning you
describe. A button on the other hand can be destroyed using unref (see
the attached program).
 
My guess is that something in your program think it is holding a
reference to the object you are unref'ing, and decrements it during its
destroy handling, perhaps the canvas is ref'ing all items or something.

As a workaround, you could write a wrapper around the objects you want
to refcount, a wrapper that doesn't unref during destroy, and simply
destroy the "real" object when the wrapper is destroyed.

	/mailund

-- 
Without order nothing can exist - without chaos nothing can evolve.
#include <gtk/gtk.h>

void
destroy (void)
{
  g_print ("destroy...\n");
}

int
main (int argc, char *argv[])
{
  GtkObject *obj;

  gtk_init (&argc, &argv);

  obj = GTK_OBJECT (gtk_button_new ());
  gtk_signal_connect (obj, "destroy", GTK_SIGNAL_FUNC (destroy), 0);

  // ref and unref
  g_print ("refcount == %d\n", obj->ref_count);
  gtk_object_ref(obj);
  g_print ("refcount == %d\n", obj->ref_count);
  gtk_object_unref(obj);
  g_print ("refcount == %d\n", obj->ref_count);
  // this destroys the object
  gtk_object_unref(obj);
  g_print ("refcount == %d\n", obj->ref_count);

  obj = GTK_OBJECT (gtk_window_new (GTK_WINDOW_TOPLEVEL));
  gtk_signal_connect (obj, "destroy", GTK_SIGNAL_FUNC (destroy), 0);

  g_print ("refcount == %d\n", obj->ref_count);
  gtk_object_ref(obj);
  g_print ("refcount == %d\n", obj->ref_count);
  gtk_object_unref(obj);
  g_print ("refcount == %d\n", obj->ref_count);
  // this destroys the object, but gives a warning
  gtk_object_unref(obj);
  g_print ("refcount == %d\n", obj->ref_count);

  
  return 0;
}


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