2013-11-28 05:11, John Emmas skrev:
Described case:On 27 Nov 2013, at 09:24, Murray Cumming wrote:I don't see any quark/object-data tests in glib/tests, and I guess there should be one, but maybe the existing tests would show some base problem.That seems like a good idea and worth pursuing but perhaps I should emphasise that my impression (albeit a 'gut feeling') is that this problem isn't necessarily connected with quark management. What seems to be happening is this:- When a Gtk::SpinButton has a Gtk::Adjustment attached, a time will eventually come when the SpinButton goes out of scope (i.e. gets destroyed). During the destruction process, "something" gets done to the attached Adjustment. AFAICT that "something" doesn't actually destroy the Adjustment - but whatever does get done includes an assumption that the Gtk::Adjustment (if still attached) will still be a valid object. Things go wrong if the Adjustment has already gone out of scope by the time the SpinButton goes out of scope. It's not impossible that there's a connection with quark management but the key to this will be to identify what exactly is "getting done" to the Adjustment during destruction of the SpinButton. If we could identify what's actually getting done, that would probably get us a lot closer to understanding this problem. John 1. The patch from bug 605728 comment 27 has been applied. 2. Important part of the code: Gtk::SpinButton* some_spin_button = new Gtk::SpinButton(); Gtk::Adjustment* some_adjuster = new Gtk::Adjustment(2, 0, 100, 1, 10, 0); some_spin_button->set_adjustment(*some_adjuster); delete some_adjuster; delete some_spin_button; This is what shall happen, and what does happen when I run the test: delete some_adjuster; Gtk::Object::~Object() calls Gtk::Object::_destroy_c_instance(), which calls g_object_unref(). The call to g_object_unref() does not remove the last reference to GtkAdjustment. Therefore Glib::ObjectBase::destroy_notify_callback_() is not called. Gtk::Object::_destroy_c_instance() calls Gtk::Object::disconnect_cpp_wrapper(), which calls g_object_steal_qdata() and g_object_set_qdata(). delete some_spin_button; Gtk::Object::~Object() calls Gtk::Object::_destroy_c_instance(), which calls g_object_unref(). The call to g_object_unref() removes the last reference to GtkSpinButton. When the last reference to GtkSpinButton is removed, it also removes its reference to GtkAdjustment. Both the GtkAdjustment and GtkSpinButton objects are finalized. Glib::ObjectBase::destroy_notify_callback_() is called for some_spin_button, and some_spin_button->gobject_ = 0, but it is not called for some_adjuster, because of the previous call to g_object_steal_qdata(). Gtk::Object::_destroy_c_instance() calls Gtk::Object::disconnect_cpp_wrapper(), which does not call g_object_steal_qdata() and g_object_set_qdata(). Note that Glib::ObjectBase::destroy_notify_callback_() is the destroy-notify function of Glib::quark_, registered by the call to g_object_set_qdata_full() in Glib::ObjectBase::_set_current_wrapper(). If Glib::quark_ is still registered with the GObject when it's finalized (its last reference is removed), then Glib::ObjectBase::destroy_notify_callback_() is called. If Glib::quark_ has been removed by a call to g_object_steal_quark(), then Glib::ObjectBase::destroy_notify_callback_() is not called. I changed the test case by allocating some_spin_button and some_adjuster dynamically. I think that makes the valgrind program more useful. I ran it, and it did not report any accesses to deallocated memory. I agree that it's a good thing with MSVC that it stores a special bit pattern in all deallocated memory. It sometimes simplifies trouble shooting but making bugs show up more promptly. But I'm convinced that the lack of that feature in gcc is not the reason why the program does not crash when I run it. Kjell |