GNOME Bugzilla – Bug 78578
Segfault when calling the MenuItem superconstructor.
Last modified: 2004-12-22 21:47:04 UTC
Hi, I'm quite new to Gtkmm, and my C++ is a bit rusty, but I don't think the program below has any errors on my part. It seems to crash in container.cc in GTK so I'm not sure if the fault is mine, GTKMM, GTK+ or GCC. I've tried this on 1.3.8 and the bug occurs, and then tried it on CVS. My compiler is GCC 2.95.4. I reduced the program right down and this is what I got: --- cut --- #include <gtkmm.h> class NewNodeMenuItem : public Gtk::MenuItem { public: NewNodeMenuItem() : Gtk::MenuItem("Node") {} Gtk::Window *my_window; }; int main(int argc, char *argv[]) { Gtk::Main main_instance (&argc, &argv); new NewNodeMenuItem(); return 0; } --- cut --- It seems the call to the superconstructor with a parameter causes a segfault. Any of the following seems to remove the problem: - calling the MenuItem constructor normally, ie with new - calling it without a parameter, ie to create a separator - removing my_window from the class To workaround I have used add_label.
Confirmed. It seems to fail somewhere in a dynamic_cast<> during the Container::add() call. Here's the backtrace (gdb) backtrace
+ Trace 20922
There are two constructors for MenuItem 1. takes an arg of Widget& 2. takes two args of GLib::ustring&, and bool mnemonic = false because of this ustring& I am going to try a little modification to the code to see if the following works. NewNodeMenuItem() : Gtk::MenuItem(new Glib::ustring("Node")) Will paste in results.
You shouldn't have a new there. That would result in a Glib::ustring*, not a Glib::ustring. Anyway, I don't expect this to make any difference.
Nope, your right no difference. After stepping through the code in order to see where the segfault occurs though, it seems to be an issue with the Glib::Object constructor. when it hits that point it crashes. I'm still investigating. (need to find out what mutable means) wasn't around when I learned c++ ;)
more accurately it seems to be in the Glib::ObjectBase constructor and with the member initialization list. ObjectBase::ObjectBase() : gobject_ (0), cpp_destruction_in_progress_(false) { } it looked like it was when the object was initializing cpp_desctruction_in_progress_ member. Im still trying to understand how this process should work.
Here is the latest. I have studied the code and nothing looks like its obviously misbehaving. After toying with the source and debugging I have come up with the following. debug with original code --- Original code --- (gdb) step 0x0804afa6 in NewNodeMenuItem::NewNodeMenuItem (this=0x806e210, __in_chrg=1) at gtkmenuitembug.cc:6 (gdb) 0x0804b1b3 in SigC::ObjectBase::ObjectBase (this=0x806e22c) at /usr/local/include/sigc++-1.2/sigc++/object.h:74 (gdb) 0x0804afd8 in NewNodeMenuItem::NewNodeMenuItem (this=0x806e210, __in_chrg=1) at gtkmenuitembug.cc:6 (gdb) Glib::ObjectBase::ObjectBase (this=0x806e234, __in_chrg=0) at objectbase.cc:39 (gdb) (gdb) Program received signal SIGSEGV, Segmentation fault. 0x40435c75 in __class_type_info::do_find_public_subobj (this=0x0, boff=0, subtype=@0x0, objptr=0x0, subptr=0x0) from /usr/local/lib/libsigc-1.1.so.3 (gdb) --- orignal code --- if any of the orginal suggestions are used to work around the issue it works, and if I change the class to class NewNodeMenuItem : public Gtk::MenuItem { public: NewNodeMenuItem() : Gtk::MenuItem("Node") {}; int i; Gtk::Window *my_window; }; then it works too. <scratches head for a minute> It looks like a compiler issue. The class is doing exactly the same thing just adding a different data memeber. when I do a backtrace with the orginal code I get: (gdb) step Program received signal SIGSEGV, Segmentation fault. 0x40435c75 in __class_type_info::do_find_public_subobj (this=0x0, boff=0, subtype=@0x0, objptr=0x0, subptr=0x0) from /usr/local/lib/libsigc-1.1.so.3 (gdb) backtrace
+ Trace 22552
... so my gut feel is a compiler issue. (virtual table is the compiler keeping track of virtual base classes) Any comments? BTW, I am using a default Mandrake 8.2 installation with a dedicated environment for gtk2/gtkmm2 development. ie. source packages in /usr/local/src packages are as follows in /usr/local/src/<dir> atk-1.0.1/ glib-2.0.1/ gtk+-2.0.2/ gtkmm-1.3.14/ gtkmm_hello-0.1.0/ intltool-0.18/ libsigc++-1.1.10/ pango-1.0.1/ pkgconfig-0.12.0/ and environment.. PATH=/usr/local/bin:$PATH LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH This one is a tricky one. ;)
Maybe someone could try changing that cpp_destruction_in_progress_ to a different type. Maybe an int, for example.
Strangely, valgrind doesn't report any problems - not even a crash. valgrind test ==515== valgrind-20020426, a memory error detector for x86 GNU/Linux. ==515== Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward. ==515== Estimated CPU clock rate is 805 MHz ==515== For more details, rerun with: -v ==515== ==515== ==515== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ==515== malloc/free: in use at exit: 6086 bytes in 89 blocks. ==515== malloc/free: 104 allocs, 15 frees, 7891 bytes allocated. ==515== For a detailed leak analysis, rerun with: --leak-check=yes ==515== For counts of detected errors, rerun with: -v
The following also crashes when __VALUE__ is one of the following: 0, 5, 6, 7, 8 #################################################### #include <gtkmm.h> #include <iostream> class NewClass : public Gtk::ImageMenuItem { public: NewClass() : Gtk::ImageMenuItem("String") {} char buf[__VALUE__]; Gtk::Window *my_window; }; int main(int argc, char *argv[]) { Gtk::Main main_instance (&argc, &argv); cout << "Sizeof Object is : " << sizeof(NewClass) << endl; new NewClass(); return 0; } ####################################################
I should have run valgrind .libs/lt-test intead. This seem more helpful: ==569== Conditional jump or move depends on uninitialised value(s) ==569== at 0x404EF58A: __class_type_info::do_find_public_subobj(int, type_info const &, void *, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404EF629: __class_type_info::do_find_public_subobj(int, type_info const &, void *, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404EF629: __class_type_info::do_find_public_subobj(int, type_info const &, void *, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404EF629: __class_type_info::do_find_public_subobj(int, type_info const &, void *, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404EF629: __class_type_info::do_find_public_subobj(int, type_info const &, void *, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404EED45: __user_type_info::dyncast(int, type_info const &, void *, type_info const &, void *) const (../../gcc/cp/tinfo.cc:773) ==569== by 0x404F06A3: __dynamic_cast_2 (../../gcc/cp/tinfo2.cc:773) ==569== by 0x40430905: Gtk::Container_Class::add_callback(_GtkContainer *, _GtkWidget *) (container.cc:496) ==569== by 0x4080E7C5: g_cclosure_marshal_VOID__OBJECT (gmarshal.c:639) ==569== by 0x407F9393: g_type_class_meta_marshal (gclosure.c:514) ==569== by 0x407F8F9A: g_closure_invoke (gclosure.c:442) ==569== by 0x4080C918: signal_emit_unlocked_R (gsignal.c:2183) ==569== by 0x4080B63E: g_signal_emit_valist (gsignal.c:2100) ==569== by 0x405F74ED: gtk_signal_emit (gtksignal.c:357) ==569== by 0x40564A36: gtk_container_add (gtkcontainer.c:860) ==569== by 0x4042FF19: Gtk::Container::add(Gtk::Widget &) (container.cc:103) ==569== by 0x404471B5: Gtk::MenuItem::add_accel_label(Glib::ustring const &, bool) (menuitem.cc:69) ==569== by 0x4044703D: Gtk::MenuItem::MenuItem(int, Glib::ustring const &, bool) (menuitem.cc:59) ==569== by 0x804AF01: main (main.cc:6) ==569== by 0x4092C507: __libc_start_main (../sysdeps/generic/libc-start.c:129)
This problem definitely happens in Container_Class::add_callback(), during the dynamic_cast<>.
The following link might be interesting??? http://gcc.gnu.org/ml/gcc-bugs/2001-08/msg00320.html
Sorry, this one is better: http://gcc.gnu.org/ml/gcc-bugs/2002-07/msg00720.html
Possibly, but that's not a real test. I don't think that a shared standalone is meaningful. What compiler are you using? I'm using gcc 2.96RH on RH7.2. I would like to hear from people using gcc 3.1 and 3.2.
Michael, could you try this on your Sun compiler. Maybe it will give us a clue.
I'm using gcc 2.96RH on RH7.1.
This isn't specific to MenuItem. It happens with Button too - its Button("something") constructor also adds a child widget. For, now the workaround would be to use the default constructor and add the child widget manually in your own constructor.
I checked this problem with g++-3.2, gtkmm 1.3.21, libsigc++ 1.1.13 and the test proggy did not crash. It seems to be a compiler problem.
I experience the segfault with gcc 2.95.3. Me too, I get stuck during the dynamic cast in Gtk::Container_Class::add_callback(). However the argument passed to dynamic_cast() is 0x1. Stepping through the code _before_ the segfault happens, I find that our instantiation of the class NewNodeMenuItem retrieved with g_object_get_qdata(object, Glib::quark_) in ObjectBase::_get_current_wrapper(object) seems to be corrupted. E.g. the data member SigC::ObejctBase::control_ suddenly is non-zero and points to some undefined piece of memory. During initialization of the wrapper I can't see anything abnormal. All data seems perfectly valid when stored with g_object_set_qdata_full() in ObjectBase::_set_current_wrapper().
Martin, I find that debuggers and printf give me a variety of different values for the pointers. Basically, that memory is corrupted. I remember Karl Nelson talking about a gcc bug that prevented use of dynamic_cast in either constructors or destructors. This looks like exactly that. It seems to be fixed in later versions of gcc, and there are workarounds for older compilers, so I'm thinking of closing this bug.
Does that mean, you will include a workaround inside gtkmm?
You already have workarounds - use different constructors. I don't see how to workaround it inside gtkmm, but I would look at any patch that you give us.
As others already said the problem seems to occur in Gtk::Container. It seems that you get the segmentation faults whenever you extend a class that is derived from Gtk::Container. I got this because I have extended Gtk::Window (gcc 2.95). The symptoms are the same as described by Martin Schulze when I add a Gtk::VBox inside my constructor. It seems to be a compiler problem because I don't have these problems when I use gcc 3.0 or gcc 3.2. Maybe we should add a comment to the system requirements of the gtkmm library that users should use a gcc version > 2.95?
> Maybe we should add a comment to the system requirements of the > gtkmm library that users should use a gcc version > 2.95? That would be wise!
Andreas, I only expect you to have this problem when you use a constructor that adds a child widget, not when you use _any_ constructor. If you think that it is impossible to derive from any Container then please give me test code. I really doubt it because there are lots of classes that derive from Container and they work fine. Yes, we do need to put this in the FAQ. We would tell people to use the workaround or upgrade their compiler if they find this problem. A later gcc is _not_ a requirement for gtkmm, because people don't _need_ to use those convenience constructors.
Murray, yes you're right. My Gtk::Window subclass calls add() in its constructor (like in the Gtk::MenuItem problem). I also agree that gcc > 2.95 is not a strict requirement. Maybe the old gcc has a problem working with object that are not yet fully initialized. The add() method call triggers some callback mechanisms that use the pointer of the new object. But as we are still in its constructor, object initialization is not yet fully finished.
Yes, I think it's a quite-well known dynamic_cast<> gcc bug. But we were confusing ourselves with other stuff. It would be nice if someone could patch the FAQ, ideally with a link to an actual gcc bug report.