Re: [gtk-list] gtk--: segfault in destructor of spinbutton!




(cc-ing to the Gtk-- mailing list)

Oliver Freyd <freyd@uni-muenster.de> writes:

> I've found out now why my app crashes on exit, when the windows are destroyed.
> A stack strace with gdb show that the Gtk_Spinbutton wants to delete its
> Gtk_Adjustment. Now I've declared both elements on the stack, so they get
> deleted automatically when the MainWindow gets destroyed. So in effect
> Gtk_Adjustment gets killed twice!

It's a bug all right. We're deleting something we have no idea if we
actually can. Also, the get_adjustment() method will crash too.
 
> So this is an ownership problem. In my opinion gtk-- should only delete
> a contained object if it was created on the heap, but not if it lives on the
> stack, as in that case it will "die" by itself, when the object it
> lives in gets out of scope. Only I have no idea how to find out if an object
> was created by "new" or just on the stack.

You can't, AFAIK. (writing our own operator new perhaps ?)
 
> Maybe someone else knows more, or should I better create everything
> with new and delete it in the destructor. But then how do I know if
> a container will delete what it contains or if I should do it
> myself?

This is precisely the problem Tero and I have been trying to tackle
(see the Gtk_SpinButton::get_adjustment() method for a scheme of the
solution): How to handle methods which return pointers to newly
created objects... You've just proved we've been a bit overzealous.

- We could be leaving it to the user to delete whatever needs to be
deleted. Since the Gtk_Adjustment can be passed as an argument to the
constructor, or set later on, there's no way we can know for sure if
the adjustment member (adjustment_widget) points to something we can
(or should) delete.

OTOH, this means that calling get_adjustment() means you have to
delete the result. Not very consistent with the gtk API, this is
supposed to be a simple accessor.

- Or, we could overload both set_adjustment() and the constructor to
take Gtk_Adjustment&, and those would set some internal flag which
would tell the destructor and get_adjustment() to leave the adjustment
member alone ?

Like this :

Gtk_SpinButton::Gtk_SpinButton(Gtk_Adjustment &adjustment,
			       gfloat climb_rate, gint digits) :
  Gtk_Entry(GTK_ENTRY(gtk_type_new(c_class.get_type()))),
  adjustment_widget(&adjustment)
{
  gtk_spin_button_construct(gtkobj(),
			    adjustment.gtkobj(),
			    climb_rate, digits);
  m_delete_adjustment = false;
}

[...]

Gtk_SpinButton::~Gtk_SpinButton()
{
  if(adjustment_widget && m_delete_adjustment) delete adjustment_widget;
}

This means the only thing the user has to take care of is not to pass
the address of a stack object to the constructor or set_adjustment(),
but that's a much lighter burden than deleting the result of a trivial
accessor IMHO.

- Finally, may be the simplest solution would be not to delete anything,
but have get_adjustment() be a simple accessor indeed, and simply
return adjustment_widget, instead of calling
gtk_spin_button_get_adjustment() and wrapping a new Gtk_Adjustment
around the result. adjustment_widget would of course be maintained by
the constructor and set_adjustment().

I prefer the third and last solution, unless some of you have better
suggestions.

-- 
					Guillaume.
					http://www.worldnet.fr/~glaurent



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