GNOME Bugzilla – Bug 91410
Gtk::Menu: non-top-level top-level window.
Last modified: 2004-12-22 21:47:04 UTC
Detected by purify, we think that Gtk::Menu objects are not properly registered. It occurs as a GtkWindow. As an aftereffect we see for instance that Gtk::Window::list_toplevels produces a memory leak with Gtk::Menu objects, because gtk_window_list_toplevels returns an object which is not associated to any C++ wrapper object. This situation is misinterpreted and Window_Class::wrap_new ist called, although the object is not a toplevel window and has to be managed.
Created attachment 10643 [details] the test case as described
Is this 2 issues? If so, please submit 2 bugs. I don't understand the first paragraph, particularly "occurs as a GtkWindow."
No, at the moment it's only one issue, which we came up during purify tests. "occurs as a GtkWindow" refers to the sample program, which show GtkWindow instead of gtkmm__GtkWindow or the given name.
I don't see what this proves, or what you are trying to prove. I don't understand why 2 top-level windows are returned by get_top_levels(). And I don't understand why _any_ top-level windows exist before you have called show() on your ExampleWindow. You could use G_OBJECT_TYPE_NAME(G_OBJECT(cppWidget.gobj())) to get the real GTK+ type. It does seem wrong that get_top_levels() returns a Window that is not top-level, but I would first like to know whether that happens with normal GTK+ code. It is not unusual to have a non "gtkmm__" widget - that's why we have wrap(), though it should not leak.
Created attachment 10669 [details] the test case with gtk+ (not gtkmm)
Created attachment 10671 [details] test case in gtk+ with extra output
The latest gtk+ example shows that the instantion of a GtkMenu object obviously also creates automatically a (surrounding) toplevel window. This seems to be the reason for the confusion we see in Gtk::Window::top_level, when it detects toplevel windows which are not C++ wrapped. BTW: All toplevel windows are contained in the toplevel list after their creation. This has nothing to do with show().
Created attachment 10684 [details] test case with gtk+ showimg top_level creation
We have looked in the GtkMenu initialization code (gtk_menu_init() in gtkmenu.c) and indeed it creates an additioon top_level. The latest form of the sample code proves that the unwrap toplevel comes from the menu object. Now that we know where these additional toplevel windows come from, we need to find a way to distinguish them from normal C++ wrapped toplevel windows. The actual handling procuces memory leaks, because an unrelated toplevel window gets wrapped automatically but is not freed at the end.
It is strange that get_is_toplevel() is true for both windows in the GTK+ examples, but not he gtkmm example.
I'd like to fix this properly, but is it a memory leak if you don't call list_toplevels()?
No, the memory leak is introduced by calling Window_Class::wrap_new() for an unrelated gtk+ object, which occured during the list iteration in toplevel_window(). Here the purify output: PLK: 36 bytes potentially leaked at 0x12ef70 This memory was allocated from: malloc [rtlib.o] c2n6Fi_Pv___1 [libCrun.so.1] void*operator new(unsigned) [rtlib.o] Glib::ObjectBase*Gtk::Window_Class::wrap_new(_GObject*) [window.cc:487] Glib::ObjectBase* Window_Class::wrap_new(GObject* o) { => return new Window((GtkWindow*)(o)); //top-level windows can not be manage()ed. } Glib::ObjectBase*__unnamed_kJQAKcVNb9wkv::create_new_wrapper(_GObject*) [wrap.cc:71] if(const gpointer idx = g_type_get_qdata(type, Glib::quark_)) { const Glib::WrapNewFunction func = (*wrap_func_table)[GPOINTER_TO_UINT(idx)]; => return (*func)(object); } } Glib::ObjectBase*Glib::wrap_auto(_GObject*,bool) [wrap.cc:138] if(!pCppObject) { // There's not already a wrapper: generate a new C++ instance. => pCppObject = create_new_wrapper(object); if(!pCppObject) {
So this isn't a very high priority because that method isn't used very much.
Is this bug still a bug? I am confused when reading the previous discussion, and I don't know how to interpert the output of the test program.
Please respond.
These examples don't prove any memory leak. And purify isn't avaiable for us to use. Maybe you could play with valgrind instead. But there is the question of why list_top_levels() is returning a non-top-level window. I have added 2 new test cases - test_gtk.c and test_gtkmm.cc. They do the same thing, with GTK+ and gtkmm. The gtkmm one returns false from is_top_level(). That's the problem that we need to solve first.
Created attachment 11361 [details] test_gtk.c
Created attachment 11362 [details] test_gtkmm.cc
This might be connected to the general bug described in #97729
No, it's not.
I noticed recently that attempting to add a new GtkMenu to a container generates a warning because GtkMenu is already in a GtkWindow. It really is that simple. Maybe we can add a special "delete get_parent()" to the Gtk::Menu destructor.
This seems to be fixed by the Glib::wrap() leak fix in gtkmm 2.2.5. Please confirm and reopen if you disagree.