GNOME Bugzilla – Bug 114568
Memory leak in Dialog::get_vbox() and get_action_area ()
Last modified: 2004-12-22 21:47:04 UTC
The following program causes memory leaks on each dialog open/close. The valgrind leak-check for one open/close and 10 open/close is appended below. If you do a diff on both valgrind outputs, you can see that valgrind reports "possibly lost" for get_vbox() and get_action_area() and "definitely lost" for pango_xft_real_render(which calls XftDrawGlyphSpec) ######################################################################## #include <gtkmm/main.h> #include <gtkmm/window.h> #include <gtkmm/dialog.h> #include <gtkmm/button.h> class MyDialog: public Gtk::Dialog { public: MyDialog() { Gtk::Button *pB = manage(new class Gtk::Button("close")); get_action_area()->pack_start(*pB); get_vbox()->set_spacing(0); pB->show(); pB->signal_clicked().connect(SigC::slot(*this, &MyDialog::on_button_clicked)); } void on_button_clicked() { hide(); response(Gtk::RESPONSE_CANCEL); } }; class MainWin: public Gtk::Window { public: MainWin() { Gtk::Button *pB = manage(new class Gtk::Button("open")); add(*pB); pB->signal_clicked().connect(SigC::slot(*this, &MainWin::on_button_clicked)); } void on_button_clicked() { MyDialog d; d.set_transient_for(*this); int res = d.run(); } }; int main(int argc, char**argv) { Gtk::Main app(&argc, &argv); MainWin mainwin; mainwin.show_all_children(); app.run(mainwin); } ######################################################################## ########################################################################## ########################################################################## ########################################################################## ########################################################################## ########################################################################## ==27614== ERROR SUMMARY: 11 errors from 2 contexts (suppressed: 20 from 2) ==27614== malloc/free: in use at exit: 466019 bytes in 6752 blocks. ==27614== malloc/free: 15961 allocs, 9209 frees, 1664981 bytes allocated. ==27614== For counts of detected errors, rerun with: -v ==27614== searching for pointers to 6752 not-freed blocks. ==27614== checked 13510452 bytes. ==27614== ==27614== 16 bytes in 1 blocks are definitely lost in loss record 86 of 446 ==27614== at 0x4015D508: malloc (vg_clientfuncs.c:100) ==27614== by 0x40A1CB45: (within /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A1D266: _XlcLocaleDirName (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A16FE2: _XlcDynamicLoad (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F7718: _XOpenLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F78D2: _XlcCurrentLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F73D8: XSupportsLocale (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40731FB0: _gdk_x11_initialize_locale (gdkim-x11.c:68) ==27614== by 0x40735825: _gdk_windowing_init (gdkmain-x11.c:99) ==27614== by 0x407089EE: gdk_parse_args (gdk.c:351) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 21 bytes in 1 blocks are definitely lost in loss record 115 of 446 ==27614== at 0x4015D508: malloc (vg_clientfuncs.c:100) ==27614== by 0x40A1CB45: (within /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A1D38B: _XlcLocaleDirName (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A16FE2: _XlcDynamicLoad (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F7718: _XOpenLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F78D2: _XlcCurrentLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F73D8: XSupportsLocale (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40731FB0: _gdk_x11_initialize_locale (gdkim-x11.c:68) ==27614== by 0x40735825: _gdk_windowing_init (gdkmain-x11.c:99) ==27614== by 0x407089EE: gdk_parse_args (gdk.c:351) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 40 bytes in 1 blocks are possibly lost in loss record 183 of 446 ==27614== at 0x4015D5F2: __builtin_new (vg_clientfuncs.c:126) ==27614== by 0x4015D62E: operator new(unsigned) (vg_clientfuncs.c:139) ==27614== by 0x402F271F: Gtk::VBox_Class::wrap_new(_GObject*) (box.cc:425) ==27614== by 0x406DAD3C: (anonymous namespace)::create_new_wrapper (_GObject*) (wrap.cc:56) ==27614== by 0x406DB016: Glib::wrap_auto(_GObject*, bool) (wrap.cc:138) ==27614== by 0x402F266B: Glib::wrap(_GtkVBox*, bool) (box.cc:383) ==27614== by 0x40305BBF: Gtk::Dialog::get_vbox() (dialog.cc:340) ==27614== by 0x804DD62: MyDialog::MyDialog() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804D92C: MainWin::on_button_clicked() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804DF54: SigC::ObjectSlot0_<void, MainWin>::proxy(void*) (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x406D4839: Glib::SignalProxyNormal::slot0_void_callback (_GObject*, void*) (signalproxy.cc:101) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EF2F7: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C14B2: gtk_button_clicked (gtkbutton.c:555) ==27614== by 0x404C21DE: gtk_real_button_released (gtkbutton.c:1044) ==27614== by 0x402F3D41: Gtk::Button_Class::released_callback (_GtkButton*) (button.cc:205) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EED3B: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C1426: gtk_button_released (gtkbutton.c:547) ==27614== by 0x404C208E: gtk_button_button_release (gtkbutton.c:969) ==27614== by 0x40368DC0: Gtk::Widget_Class::button_release_event_callback(_GtkWidget*, _GdkEventButton*) (widget.cc:3669) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x4053339F: gtk_propagate_event (gtkmain.c:2267) ==27614== by 0x40532436: gtk_main_do_event (gtkmain.c:1502) ==27614== by 0x4072D175: gdk_event_dispatch (gdkevents-x11.c:2047) ==27614== by 0x4083F4DA: g_main_dispatch (gmain.c:1653) ==27614== by 0x408403DC: g_main_context_dispatch (gmain.c:2209) ==27614== by 0x408406E2: g_main_context_iterate (gmain.c:2249) ==27614== by 0x40840D31: g_main_loop_run (gmain.c:2498) ==27614== by 0x40531CEE: gtk_main (gtkmain.c:1092) ==27614== by 0x4031AF01: Gtk::Main::run_impl() (main.cc:470) ==27614== by 0x4031ADA0: Gtk::Main::run(Gtk::Window&) (main.cc:424) ==27614== by 0x804D436: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 40 bytes in 1 blocks are possibly lost in loss record 184 of 446 ==27614== at 0x4015D5F2: __builtin_new (vg_clientfuncs.c:126) ==27614== by 0x4015D62E: operator new(unsigned) (vg_clientfuncs.c:139) ==27614== by 0x402F5E47: Gtk::HButtonBox_Class::wrap_new(_GObject*) (buttonbox.cc:343) ==27614== by 0x406DAD3C: (anonymous namespace)::create_new_wrapper (_GObject*) (wrap.cc:56) ==27614== by 0x406DB016: Glib::wrap_auto(_GObject*, bool) (wrap.cc:138) ==27614== by 0x402F5D93: Glib::wrap(_GtkHButtonBox*, bool) (buttonbox.cc:301) ==27614== by 0x40305C27: Gtk::Dialog::get_action_area() (dialog.cc:350) ==27614== by 0x804DD49: MyDialog::MyDialog() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804D92C: MainWin::on_button_clicked() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804DF54: SigC::ObjectSlot0_<void, MainWin>::proxy(void*) (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x406D4839: Glib::SignalProxyNormal::slot0_void_callback (_GObject*, void*) (signalproxy.cc:101) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EF2F7: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C14B2: gtk_button_clicked (gtkbutton.c:555) ==27614== by 0x404C21DE: gtk_real_button_released (gtkbutton.c:1044) ==27614== by 0x402F3D41: Gtk::Button_Class::released_callback (_GtkButton*) (button.cc:205) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EED3B: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C1426: gtk_button_released (gtkbutton.c:547) ==27614== by 0x404C208E: gtk_button_button_release (gtkbutton.c:969) ==27614== by 0x40368DC0: Gtk::Widget_Class::button_release_event_callback(_GtkWidget*, _GdkEventButton*) (widget.cc:3669) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x4053339F: gtk_propagate_event (gtkmain.c:2267) ==27614== by 0x40532436: gtk_main_do_event (gtkmain.c:1502) ==27614== by 0x4072D175: gdk_event_dispatch (gdkevents-x11.c:2047) ==27614== by 0x4083F4DA: g_main_dispatch (gmain.c:1653) ==27614== by 0x408403DC: g_main_context_dispatch (gmain.c:2209) ==27614== by 0x408406E2: g_main_context_iterate (gmain.c:2249) ==27614== by 0x40840D31: g_main_loop_run (gmain.c:2498) ==27614== by 0x40531CEE: gtk_main (gtkmain.c:1092) ==27614== by 0x4031AF01: Gtk::Main::run_impl() (main.cc:470) ==27614== by 0x4031ADA0: Gtk::Main::run(Gtk::Window&) (main.cc:424) ==27614== by 0x804D436: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 800 bytes in 20 blocks are possibly lost in loss record 344 of 433 ==27614== at 0x4015D978: calloc (vg_clientfuncs.c:242) ==27614== by 0x40844317: g_malloc0 (gmem.c:153) ==27614== by 0x407F0D9D: type_node_any_new_W (gtype.c:290) ==27614== by 0x407F108F: type_node_fundamental_new_W (gtype.c:367) ==27614== by 0x407F775A: g_type_init_with_debug_flags (gtype.c:3057) ==27614== by 0x407F787D: g_type_init (gtype.c:3115) ==27614== by 0x407089E3: gdk_parse_args (gdk.c:347) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 1056 bytes in 12 blocks are definitely lost in loss record 373 of 446 ==27614== at 0x4015D978: calloc (vg_clientfuncs.c:242) ==27614== by 0x409C7890: XCreateImage (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409C5C9F: XGetImage (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40973075: XftGlyphSpecCore (in /usr/lib/libXft.so.2.0) ==27614== by 0x40975BD8: XftDrawGlyphSpec (in /usr/lib/libXft.so.2.0) ==27614== by 0x407834C8: pango_xft_real_render (pangoxft-font.c:362) ==27614== by 0x407838C4: pango_xft_render (pangoxft-font.c:391) ==27614== by 0x4072A26C: gdk_x11_draw_glyphs (gdkdrawable-x11.c:842) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x40713C38: gdk_pixmap_draw_glyphs (gdkpixmap.c:369) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x4071E451: gdk_window_draw_glyphs (gdkwindow.c:1770) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x407100F3: gdk_draw_layout_line_with_colors (gdkpango.c:303) ==27614== by 0x4071053A: gdk_draw_layout_with_colors (gdkpango.c:395) ==27614== by 0x407107AB: gdk_draw_layout (gdkpango.c:452) ==27614== by 0x40579670: gtk_default_draw_layout (gtkstyle.c:4983) ==27614== by 0x4057B2BC: gtk_paint_layout (gtkstyle.c:5914) ==27614== by 0x40523057: gtk_label_expose (gtklabel.c:1813) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x404E7407: gtk_container_propagate_expose (/sq2000/data/sim/linux/gcc-3.2.native/include/glib- 2.0/gobject/gobjectnotifyqueue.c:68) ==27614== by 0x404E711A: gtk_container_expose_child (gtkcontainer.c:2288) ==27614== by 0x404BC52C: gtk_bin_forall (gtkbin.c:179) ==27614== by 0x403022A7: Gtk::Container_Class::forall_vfunc_callback (_GtkContainer*, int, void (*)(_GtkWidget*, void*), void*) (container.cc:391) ==27614== by 0x404E575C: gtk_container_forall (gtkcontainer.c:1271) ==27614== by 0x404E7197: gtk_container_expose (gtkcontainer.c:2322) ==27614== by 0x404C1FFF: gtk_button_expose (gtkbutton.c:934) ==27614== by 0x403690B0: Gtk::Widget_Class::expose_event_callback (_GtkWidget*, _GdkEventExpose*) (widget.cc:3817) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x404E7407: gtk_container_propagate_expose (/sq2000/data/sim/linux/gcc-3.2.native/include/glib- 2.0/gobject/gobjectnotifyqueue.c:68) ==27614== by 0x404E711A: gtk_container_expose_child (gtkcontainer.c:2288) ==27614== by 0x404BC52C: gtk_bin_forall (gtkbin.c:179) ==27614== by 0x403036A3: Gtk::Container::forall_vfunc(int, void (*) (_GtkWidget*, void*), void*) (container.cc:915) ==27614== by 0x403022C1: Gtk::Container_Class::forall_vfunc_callback (_GtkContainer*, int, void (*)(_GtkWidget*, void*), void*) (container.cc:391) ==27614== by 0x404E575C: gtk_container_forall (gtkcontainer.c:1271) ==27614== by 0x404E7197: gtk_container_expose (gtkcontainer.c:2322) ==27614== by 0x405FC932: gtk_window_expose (gtkwindow.c:5396) ==27614== by 0x4036EEF8: Gtk::Widget::on_expose_event(_GdkEventExpose*) (widget.cc:6439) ==27614== ==27614== LEAK SUMMARY: ==27614== definitely lost: 1269 bytes in 16 blocks. ==27614== possibly lost: 968 bytes in 23 blocks. ==27614== still reachable: 463782 bytes in 6713 blocks. ==27614== suppressed: 0 bytes in 0 blocks. ==27614== Reachable blocks (those to which a pointer was found) are not shown. ==27614== To see them, rerun with: --show-reachable=yes ########################################################################## ########################################################################## ########################################################################## ########################################################################## ########################################################################## ########################################################################## ==27614== ERROR SUMMARY: 47 errors from 2 contexts (suppressed: 20 from 2) ==27614== malloc/free: in use at exit: 529995 bytes in 6743 blocks. ==27614== malloc/free: 22674 allocs, 15931 frees, 1903107 bytes allocated. ==27614== For counts of detected errors, rerun with: -v ==27614== searching for pointers to 6743 not-freed blocks. ==27614== checked 13574756 bytes. ==27614== ==27614== 16 bytes in 1 blocks are definitely lost in loss record 83 of 433 ==27614== at 0x4015D508: malloc (vg_clientfuncs.c:100) ==27614== by 0x40A1CB45: (within /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A1D266: _XlcLocaleDirName (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A16FE2: _XlcDynamicLoad (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F7718: _XOpenLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F78D2: _XlcCurrentLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F73D8: XSupportsLocale (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40731FB0: _gdk_x11_initialize_locale (gdkim-x11.c:68) ==27614== by 0x40735825: _gdk_windowing_init (gdkmain-x11.c:99) ==27614== by 0x407089EE: gdk_parse_args (gdk.c:351) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 21 bytes in 1 blocks are definitely lost in loss record 111 of 433 ==27614== at 0x4015D508: malloc (vg_clientfuncs.c:100) ==27614== by 0x40A1CB45: (within /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A1D38B: _XlcLocaleDirName (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40A16FE2: _XlcDynamicLoad (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F7718: _XOpenLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F78D2: _XlcCurrentLC (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409F73D8: XSupportsLocale (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40731FB0: _gdk_x11_initialize_locale (gdkim-x11.c:68) ==27614== by 0x40735825: _gdk_windowing_init (gdkmain-x11.c:99) ==27614== by 0x407089EE: gdk_parse_args (gdk.c:351) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 400 bytes in 10 blocks are possibly lost in loss record 313 of 433 ==27614== at 0x4015D5F2: __builtin_new (vg_clientfuncs.c:126) ==27614== by 0x4015D62E: operator new(unsigned) (vg_clientfuncs.c:139) ==27614== by 0x402F271F: Gtk::VBox_Class::wrap_new(_GObject*) (box.cc:425) ==27614== by 0x406DAD3C: (anonymous namespace)::create_new_wrapper (_GObject*) (wrap.cc:56) ==27614== by 0x406DB016: Glib::wrap_auto(_GObject*, bool) (wrap.cc:138) ==27614== by 0x402F266B: Glib::wrap(_GtkVBox*, bool) (box.cc:383) ==27614== by 0x40305BBF: Gtk::Dialog::get_vbox() (dialog.cc:340) ==27614== by 0x804DD62: MyDialog::MyDialog() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804D92C: MainWin::on_button_clicked() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804DF54: SigC::ObjectSlot0_<void, MainWin>::proxy(void*) (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x406D4839: Glib::SignalProxyNormal::slot0_void_callback (_GObject*, void*) (signalproxy.cc:101) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EF2F7: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C14B2: gtk_button_clicked (gtkbutton.c:555) ==27614== by 0x404C21DE: gtk_real_button_released (gtkbutton.c:1044) ==27614== by 0x402F3D41: Gtk::Button_Class::released_callback (_GtkButton*) (button.cc:205) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EED3B: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C1426: gtk_button_released (gtkbutton.c:547) ==27614== by 0x404C208E: gtk_button_button_release (gtkbutton.c:969) ==27614== by 0x40368DC0: Gtk::Widget_Class::button_release_event_callback(_GtkWidget*, _GdkEventButton*) (widget.cc:3669) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x4053339F: gtk_propagate_event (gtkmain.c:2267) ==27614== by 0x40532436: gtk_main_do_event (gtkmain.c:1502) ==27614== by 0x4072D175: gdk_event_dispatch (gdkevents-x11.c:2047) ==27614== by 0x4083F4DA: g_main_dispatch (gmain.c:1653) ==27614== by 0x408403DC: g_main_context_dispatch (gmain.c:2209) ==27614== by 0x408406E2: g_main_context_iterate (gmain.c:2249) ==27614== by 0x40840D31: g_main_loop_run (gmain.c:2498) ==27614== by 0x40531CEE: gtk_main (gtkmain.c:1092) ==27614== by 0x4031AF01: Gtk::Main::run_impl() (main.cc:470) ==27614== by 0x4031ADA0: Gtk::Main::run(Gtk::Window&) (main.cc:424) ==27614== by 0x804D436: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 400 bytes in 10 blocks are possibly lost in loss record 314 of 433 ==27614== at 0x4015D5F2: __builtin_new (vg_clientfuncs.c:126) ==27614== by 0x4015D62E: operator new(unsigned) (vg_clientfuncs.c:139) ==27614== by 0x402F5E47: Gtk::HButtonBox_Class::wrap_new(_GObject*) (buttonbox.cc:343) ==27614== by 0x406DAD3C: (anonymous namespace)::create_new_wrapper (_GObject*) (wrap.cc:56) ==27614== by 0x406DB016: Glib::wrap_auto(_GObject*, bool) (wrap.cc:138) ==27614== by 0x402F5D93: Glib::wrap(_GtkHButtonBox*, bool) (buttonbox.cc:301) ==27614== by 0x40305C27: Gtk::Dialog::get_action_area() (dialog.cc:350) ==27614== by 0x804DD49: MyDialog::MyDialog() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804D92C: MainWin::on_button_clicked() (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x804DF54: SigC::ObjectSlot0_<void, MainWin>::proxy(void*) (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x406D4839: Glib::SignalProxyNormal::slot0_void_callback (_GObject*, void*) (signalproxy.cc:101) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EF2F7: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C14B2: gtk_button_clicked (gtkbutton.c:555) ==27614== by 0x404C21DE: gtk_real_button_released (gtkbutton.c:1044) ==27614== by 0x402F3D41: Gtk::Button_Class::released_callback (_GtkButton*) (button.cc:205) ==27614== by 0x407EF80F: g_cclosure_marshal_VOID__VOID (gmarshal.c:77) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EED3B: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE595: g_signal_emit_valist (gsignal.c:2535) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x404C1426: gtk_button_released (gtkbutton.c:547) ==27614== by 0x404C208E: gtk_button_button_release (gtkbutton.c:969) ==27614== by 0x40368DC0: Gtk::Widget_Class::button_release_event_callback(_GtkWidget*, _GdkEventButton*) (widget.cc:3669) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x4053339F: gtk_propagate_event (gtkmain.c:2267) ==27614== by 0x40532436: gtk_main_do_event (gtkmain.c:1502) ==27614== by 0x4072D175: gdk_event_dispatch (gdkevents-x11.c:2047) ==27614== by 0x4083F4DA: g_main_dispatch (gmain.c:1653) ==27614== by 0x408403DC: g_main_context_dispatch (gmain.c:2209) ==27614== by 0x408406E2: g_main_context_iterate (gmain.c:2249) ==27614== by 0x40840D31: g_main_loop_run (gmain.c:2498) ==27614== by 0x40531CEE: gtk_main (gtkmain.c:1092) ==27614== by 0x4031AF01: Gtk::Main::run_impl() (main.cc:470) ==27614== by 0x4031ADA0: Gtk::Main::run(Gtk::Window&) (main.cc:424) ==27614== by 0x804D436: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 800 bytes in 20 blocks are possibly lost in loss record 344 of 433 ==27614== at 0x4015D978: calloc (vg_clientfuncs.c:242) ==27614== by 0x40844317: g_malloc0 (gmem.c:153) ==27614== by 0x407F0D9D: type_node_any_new_W (gtype.c:290) ==27614== by 0x407F108F: type_node_fundamental_new_W (gtype.c:367) ==27614== by 0x407F775A: g_type_init_with_debug_flags (gtype.c:3057) ==27614== by 0x407F787D: g_type_init (gtype.c:3115) ==27614== by 0x407089E3: gdk_parse_args (gdk.c:347) ==27614== by 0x4053169E: gtk_parse_args (gtkmain.c:657) ==27614== by 0x40531B09: gtk_init_check (gtkmain.c:870) ==27614== by 0x40531B49: gtk_init (gtkmain.c:902) ==27614== by 0x4031AC3D: Gtk::Main::init(int*, char***, bool) (main.cc:375) ==27614== by 0x4031A91B: Gtk::Main::Main(int*, char***, bool) (main.cc:329) ==27614== by 0x804D407: main (in /home/ehopfha/src/gtkdialog/a.out) ==27614== by 0x420158D3: __libc_start_main (in /lib/i686/libc-2.2.93.so) ==27614== by 0x804D354: (within /home/ehopfha/src/gtkdialog/a.out) ==27614== ==27614== 6072 bytes in 69 blocks are definitely lost in loss record 416 of 433 ==27614== at 0x4015D978: calloc (vg_clientfuncs.c:242) ==27614== by 0x409C7890: XCreateImage (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x409C5C9F: XGetImage (in /usr/X11R6/lib/libX11.so.6.2) ==27614== by 0x40973075: XftGlyphSpecCore (in /usr/lib/libXft.so.2.0) ==27614== by 0x40975BD8: XftDrawGlyphSpec (in /usr/lib/libXft.so.2.0) ==27614== by 0x407834C8: pango_xft_real_render (pangoxft-font.c:362) ==27614== by 0x407838C4: pango_xft_render (pangoxft-font.c:391) ==27614== by 0x4072A26C: gdk_x11_draw_glyphs (gdkdrawable-x11.c:842) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x40713C38: gdk_pixmap_draw_glyphs (gdkpixmap.c:369) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x4071E451: gdk_window_draw_glyphs (gdkwindow.c:1770) ==27614== by 0x4070B5B8: gdk_draw_glyphs (gdkdraw.c:889) ==27614== by 0x407100F3: gdk_draw_layout_line_with_colors (gdkpango.c:303) ==27614== by 0x4071053A: gdk_draw_layout_with_colors (gdkpango.c:395) ==27614== by 0x407107AB: gdk_draw_layout (gdkpango.c:452) ==27614== by 0x40579670: gtk_default_draw_layout (gtkstyle.c:4983) ==27614== by 0x4057B2BC: gtk_paint_layout (gtkstyle.c:5914) ==27614== by 0x40523057: gtk_label_expose (gtklabel.c:1813) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x404E7407: gtk_container_propagate_expose (/sq2000/data/sim/linux/gcc-3.2.native/include/glib- 2.0/gobject/gobjectnotifyqueue.c:68) ==27614== by 0x404E711A: gtk_container_expose_child (gtkcontainer.c:2288) ==27614== by 0x404BC52C: gtk_bin_forall (gtkbin.c:179) ==27614== by 0x403022A7: Gtk::Container_Class::forall_vfunc_callback (_GtkContainer*, int, void (*)(_GtkWidget*, void*), void*) (container.cc:391) ==27614== by 0x404E575C: gtk_container_forall (gtkcontainer.c:1271) ==27614== by 0x404E7197: gtk_container_expose (gtkcontainer.c:2322) ==27614== by 0x404C1FFF: gtk_button_expose (gtkbutton.c:934) ==27614== by 0x403690B0: Gtk::Widget_Class::expose_event_callback (_GtkWidget*, _GdkEventExpose*) (widget.cc:3817) ==27614== by 0x40533574: _gtk_marshal_BOOLEAN__BOXED (gtkmarshalers.c:82) ==27614== by 0x407DFC19: g_type_class_meta_marshal (gclosure.c:514) ==27614== by 0x407DF979: g_closure_invoke (gclosure.c:437) ==27614== by 0x407EEF3F: signal_emit_unlocked_R (gsignal.c:2664) ==27614== by 0x407EE3C4: g_signal_emit_valist (gsignal.c:2564) ==27614== by 0x407EE78E: g_signal_emit (gsignal.c:2612) ==27614== by 0x405EFB92: gtk_widget_event_internal (gtkwidget.c:3143) ==27614== by 0x404E7407: gtk_container_propagate_expose (/sq2000/data/sim/linux/gcc-3.2.native/include/glib- 2.0/gobject/gobjectnotifyqueue.c:68) ==27614== by 0x404E711A: gtk_container_expose_child (gtkcontainer.c:2288) ==27614== by 0x404BC52C: gtk_bin_forall (gtkbin.c:179) ==27614== by 0x403036A3: Gtk::Container::forall_vfunc(int, void (*) (_GtkWidget*, void*), void*) (container.cc:915) ==27614== by 0x403022C1: Gtk::Container_Class::forall_vfunc_callback (_GtkContainer*, int, void (*)(_GtkWidget*, void*), void*) (container.cc:391) ==27614== by 0x404E575C: gtk_container_forall (gtkcontainer.c:1271) ==27614== by 0x404E7197: gtk_container_expose (gtkcontainer.c:2322) ==27614== by 0x405FC932: gtk_window_expose (gtkwindow.c:5396) ==27614== by 0x4036EEF8: Gtk::Widget::on_expose_event(_GdkEventExpose*) (widget.cc:6439) ==27614== ==27614== LEAK SUMMARY: ==27614== definitely lost: 6109 bytes in 71 blocks. ==27614== possibly lost: 1600 bytes in 40 blocks. ==27614== still reachable: 522286 bytes in 6632 blocks. ==27614== suppressed: 0 bytes in 0 blocks. ==27614== Reachable blocks (those to which a pointer was found) are not shown. ==27614== To see them, rerun with: --show-reachable=yes
Created attachment 17228 [details] Source-code of test program.
Created attachment 17229 [details] Valgrind output of 1 open/close action
Created attachment 17230 [details] Valgrind output of 10 open/close action
Somebody should do the following: - Simplify this test case even more. - Find out when destructors are or are not being called. - Find out if there are any orphaned references. Use the reference-couting debug output. I think it's the --enable-debug-refcounting configure option, or something similar - see glib/glibmm/debug.
Created attachment 17543 [details] test_simpler.cc
I can not reproduce this on my system. Please tell us exactly what valgrind arguments you are using. Also, you seem to mention 2 bugs rather than one. Do you still have the problem with this simplified test case (test_simpler.cc) that exercises just one of the mentioned methods?
Created attachment 17702 [details] Valgrind output of test_simpler.cc (including valgrind cmd-line args)
All I get for the "--enable-debug-refcounting" and test_simpler.cc (no matter how often I open/close the dialog) is the following: (main:20415): gtkmm-DEBUG: file object.cc: line 69 (void Gtk::Object::_init_unmanage(bool)): ref: C++ instance: 0x80820d0; C instance: 0x8083358, ref_count = 1, type = gtkmm__GtkButton
The issue of 2 or 1 bugs. Well sure it looks for me like 2 bugs also, but if it is caused by some RefPtr problem in Gtkmm it might be only 1, but who knows....
I said "Do you still have the problem with this simplified test case (test_simpler.cc) that exercises just one of the mentioned methods?" Use of --debug-refcounting is not necessary to tell me whether the problem still exists with test_simpler.cc. Re. the number of bugs: Simple test cases are easier to deal with. We need to isolate the bug before fixing it.
Yes, check the new Attachment. There you can see that the problem remains.
My Compiler version is: --------------------------------------------------- Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man -- infodir=/usr/share/info --enable-shared --enable-threads=posix -- disable-checking --host=i386-redhat-linux --with-system-zlib --enable- __cxa_atexit Thread model: posix gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7) --------------------------------------------------- What is yours?
I will check if the problem remains with gcc 3.3.
Created attachment 17705 [details] test_simpler_gcc3_3.valgrind.txt
The problem remains with gcc-3.3 also.
Also I should tell that we are using - atk-1.0.3 - glib-2.0.7 - gtk+-2.0.9 - gtkmm-2.0.2 - libsigc++-1.2.2 - pango-1.0.5 - pkgconfig-0.13.0 and I tested also with - atk-1.2.0 - glib-2.2.1 - gtk+-2.2.1 - gtkmm-2.2.3 - libsigc++-1.2.4 - pango-1.2.1 - pkgconfig-0.14.0.tar.gz
OK, I will investigate when I get a chance. I was not using the same valgrind command. But you are capable of investigating yourself.
Maybe a solution (look at the end of this entry) - VBox* Dialog::get_vbox() calls Glib::wrap with (implicitly) take_copy = false - Glib::wrap (inside gtkmm/box.cc !!) calls Glib::wrap_auto by forwarding take_copy = false - Glib::wrap_auto calls create_new_wrapper(object) if static_cast<ObjectBase*>(g_object_get_qdata(object, Glib::quark_)) returns NULL - create_new_wrapper does a cast for the result of g_object_get_qdata() to bool which is of type gpointer normally. Assuming that a not NULL means the same as true, it calls Gtk::VBox_Class::wrap_new() by using a function pointer - The Gtk::VBox_Class::wrap_new() creates a new instance and does (STRANGE) a manage on the result pointer. ---------------------------------------------------------- As no function does a g_object_set_qdata (!!!) it will repeatingly create new instances. I think anyway there should be only one (or better NONE) copy of the vbox per dialog???? All this stuff does one vbox for all dialogs if it would work correctly???
Just found that Gtk::ObjectBase::_set_current_wrapper calls g_object_set_qdata_full. Gtk::ObjectBase::_set_current_wrapper is called by Gtk::ObjectBase::initialize which is called by the ctor of Gtk::Object so we are back at the beginning.
Just a qustion: Does the Gtk::Dialog normally have a member object of type Gtk::VBox? I assume "No". Therefor the method Gtk::Dialog::get_vbox() (no matter how often called) creates one instance of a wrapper Gtk::VBox that is never cleaned up??? So that "wrapper instance" should be a managed object of the class Gtk::Dialog, so it gets deleted when the Gtk::Dialog is destroyed??
The phrase "managed object of the class Gtk::Dialog" should be "managed object of the object of class Gtk::Dialog" (to prevent confusion)
Another question: Does a destruction of a wrapper object always destroy the wrapped object? If yes, that would be a problem to the above solution.
No, there is no Gtk::VBox member variable in Gtk::Dialog. Yes, I would expect anything from Glib::wrap() to be manage()ed. The manage() just means that the lifetime will be controlled by the GTK+ container, as per normal, not by anything in C++. Sooner or later GTK+ should call destroy on that GtkVBox, and the Gtk::VBox will then be destroyed in response. You need to check whether the GtkVBox is being destroyed. If not, you need to check whether it would be destroyed in a C example. Here is a clue about how to check whether it is being destroyed: http://bugzilla.gnome.org/showattachment.cgi?attach_id=16433 (That's from bug 111084). You can use gobj() in your C++ example - you don't need to write the whole thing in C just to test this one thing.
Yes, destroying a C++ instance always destroys the underlying C instance. The lifetimes of widgets and their C++ wrappers should be very tightly bound.
Created attachment 17727 [details] test_combo.cc (shows the problem for ComboBox also)
Forgot to replace the ToggleButton with Button in the test_combo.cc example.
Created attachment 17728 [details] New test_combo.cc
With this new test_combo.cc it is possible to verify the memory-leak with the Linux-"top" tool also. So you can see that this is not only a short-term effect.
Murray, you are writing: Sooner or later GTK+ should call destroy on that GtkVBox, and the Gtk::VBox will then be destroyed in response. Question: How can the GtkVBox cause that a Gtk::VBox is destroyed?
I didn't do the check (with the example you told me) if GtkVBox is being destroyed yet, but valgrind tells me that there is no instance of it anymore. Only one/more instances of Gtk::VBox are left (according to valgrind)
Still my assumption is, that for each Gtk::Dialog there is one Gtk::VBox (wrapper) instance that does not get deleted when destroying the Gtk::Dialog.
> How can the GtkVBox cause that a Gtk::VBox is destroyed? There is a callback. This is probably an interesting part to look at: http://cvs.gnome.org/lxr/source/gtkmm-root/gtk-src/object.ccg#205 (watch out - the cvs directory structure is totally different than a real checkout or a tarball). You should really check that the GtkVBox is destroyed. I wouldn't just trust valgrind to tell me that. And if it destroyed then I would try to find out why the Gtk::VBox is not also destroyed. You are doing well. I have meant to write a lifetime document for a long time. The //GTKMM_LIFECYCLE comments are what I will look at when I do that.
Created attachment 17730 [details] gtk_plus_destroy_src.txt
Created attachment 17731 [details] gtk_plus_destroy_out.txt
The on_vbox_destroyed for the GtkVBox appears, but no destruction of the Gtk::VBox. Note: The --enable-debug-refcounting seems not to work, so I added "#define DEF_DEBUG_REFCOUNTING" to gtkmmconfig.h so you can see the results in the attachment gtk_plus_destroy_out.txt
Created attachment 17732 [details] gtk_plus_destroy_src2.txt
Created attachment 17733 [details] gtk_plus_destroy_out2.txt
> no destruction of the Gtk::VBox. In the past I have double-checked this by using a derived class and putting a std::cout in the derived destructor. If we are sure that the C instance is being destroyed without the C++ instance being destroyed, then we need to check whether the destroy callback in gtkmm is being called. And if not, why not. > The --enable-debug-refcounting seems not to work. Maybe I remembered the name wrong. I'm sure I've used it recently. It should be visible in ./configure --help. Sorry, I can't check now. It would be best to do it properly.
By the way, I know it's unpleasant to switch our minds into C mode for a few moments. Remember, it's only for a while.
If the callback is not being called, something like the following is missing somewhere: g_signal_connect (object, "destroy", G_CALLBACK (&callback_destroy_), this) Am I right?
Well, it's probably a bit more subtle/complicated than that. And I think we actually specify a qdata callback. It would be best to find the callback then grep for it. object_base.cc is probably the place to look.
The callback for the VBox is registered in ObjectBase::_set_current_wrapper with the following(I added some debug-statements): g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_) but ObjectBase::destroy_notify_callback_ is never called for the VBox.
I added the following line in function on_vbox_destroyed() of gtk_plus_destroy_src.txt: g_warning("Data of GtkVBox: refcount: %d\n", ((GObject*)object)->ref_count); And the output is: ** (main:9732): WARNING **: Data of GtkVBox: refcount: 3 How is that to be understood?
> but ObjectBase::destroy_notify_callback_ is never called for the VBox. If we are on the right track (it's easy to get lost): Maybe the destroy_notify is called when the GtkVBox widget is about to be destroyed. (There is a 2-stage destroy process in GTK+). And maybe it never actually gets destroyed because something stops the destroy process. I would investigate any destroy callbacks in GTK+ for GtkVBox or its base "classes". I would throw a few debug statements in there. > I added the following line in function on_vbox_destroyed > ... > How is that to be understood? It's saying that 3 things still have references to the GtkVBox when it is being destroyed. That might, or might not, be a problem. It's not unusual to destroy things while they are being used. The other things just stop using it. Sometimes the unusual route that gtkmm takes through the GTK+ code means that there is an orphaned reference somewhere. Sometimes GTK+ code does not expect this and does unusual code. But I am just speculating. Whatever the solution is, it will look simple in the end.
There is a strange comment in method Container_Class::destroy_callback of http://cvs.gnome.org/lxr/source/gtkmm-root/gtk-src/container.ccg : This happens in Gtk::Widget::dispose_vfunc() instead but there is only a Gtk::Widget_Class::dispose_vfunc_callback() which is never called.
gtk_object_destroy for GtkVBox is called just before my Testprogram displays "on_vbox_destroyed"
And after displaying "on_vbox_destroyed", the function gtk_container_destroy gets called for GtkVBox.
I correct myself: Gtk::Widget_Class::dispose_vfunc_callback() is called, but only for the gtkmm__GtkDialog.
Also gtk_object_real_destroy gets called for GtkVBox.
In gtk_object_dispose I see only a gtk_signal_emit (object, object_signals[DESTROY]); but where is the g_object_set_qdata_full stuff called?
Here is the overall oder of events: gtk_widget_destroy: GtkVBox gtk_object_destroy: GtkVBox ** (main:26364): WARNING **: on_vbox_destroyed ** (main:26364): WARNING **: Data of GtkVBox: refcount: 3 gtk_container_destroy: GtkVBox gtk_widget_real_destroy: GtkVBox gtk_object_real_destroy: GtkVBox
OK, so my previous suggestion still seems to be relevant: "Maybe the destroy_notify is called when the GtkVBox widget is about to be destroyed. (There is a 2-stage destroy process in GTK+). And maybe it never actually gets destroyed because something stops the destroy process. I would investigate any destroy callbacks in GTK+ for GtkVBox or its base "classes". I would throw a few debug statements in there." As an extra hint, I think that 2nd stage is called "dispose".
Murry: Did you ever have the case before that the notify didn't get called? I mean in a previous bug. If so, what was that reason before?
Hmm, I think this bugs had that problem: http://bugzilla.gnome.org/show_bug.cgi?id=111084
I found another maybe relevant bug http://bugzilla.gnome.org/show_bug.cgi?id=91404
I am not at my desk, so I can't do any debugging yet, but.... Inside the method Container_Class::destroy_callback(GtkObject* self) I see the following statement if(cppChild && !cppChild->is_managed_()) And in my previous comments I was showing that the GTk::VBox is managed object of the (Singleton?)Gtk::VBox_Class Might that be a problem?
I don't think so. The whole point of that code is explained in the comment at the start of the method: // We need to remove non-manage()ed widgets to prevent gtk_container_destroy() from destroying them. // Contary to what we thought once, even non-floating (sunk) widgets are destroyed by gtk_container_destroy() It should have no effect on manage()ed widgets
Here is the updated oder of events: (including the "dispose") gtk_widget_destroy: GtkVBox gtk_object_destroy: GtkVBox gtk_object_dispose: GtkVBox gtk_object_dispose: GtkVBox calling gtk_signal_emit ** (main:26364): WARNING **: on_vbox_destroyed ** (main:26364): WARNING **: Data of GtkVBox: refcount: 3 gtk_container_destroy: GtkVBox gtk_widget_real_destroy: GtkVBox gtk_object_real_destroy: GtkVBox
Created attachment 17759 [details] g_object_qdata_out.txt
I find the place where the signals for g_signal_connect(G_OBJECT(vbo), "destroy", G_CALLBACK(on_vbox_destroyed), 0); of my test program is emitted, but I have no clue where the signal (?? is it one) for g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_); is emitted? Somewhere should be a g_object_get_qdata(Glib::quark_) and some lines later a function call to the return value of g_object_get_qdata But as Glib::quark_ is only defined inside GTKMM how should it be possible that the callback is triggered from GTK+?
What happens if I explicitly delete the Gtk::VBox wrapper of the GtkVBox if the GtkVBox is already deleted? Should work, shouldn't it? I am not so deep into the GTKMM or GTK+ stuff that I will be able to find the bug, so I think it is better if I delete the Gtk::VBox myself.
Just a last thought: Maybe g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_); inside ObjectBase::_set_current_wrapper should be replaced with g_signal_connect(G_OBJECT(vbo), "destroy", G_CALLBACK(on_vbox_destroyed), 0); as this one is really called by the "gtk_object_dispose"
You have done a lot of good work here and it will help me to find the bug. Well done and thank you. I'll try to find some time this evening. Yes, deleting a C++ instance that has no underlying C instance should work, but I've never tried it because it should never be possible. Well, if you delete it now then it will be double-delete when I fix the bug. I'm interested, in what kind of application is the occasional leak based on GUI interaction such a critical problem? re. dispose: Maybe. I will investigate. It has worked so far elsewhere.
We have a application where we pop up many Gtk::Dialogs for data input. The application is supposed to run several hours, maybe days or weeks or even month (I actually dont believe that, but my boss does) And in the gtkmm 2.0 there was only a little memory leak whereas my collegue (she found the leak originally) said that with gtkmm2.2 the memory leak was even bigger. I have to ask her how much memory it actually was.
I will try that "g_signal_connect" once, if it doesn't work I'll give up.
Huuuuuuurrrrrrrraaaaaaayyyyyyy! It worked!!! ################################################################## void ObjectBase::tmp_on_destroyed(GObject* object, gpointer data) { ObjectBase::destroy_notify_callback_(data); } void ObjectBase::_set_current_wrapper(GObject* object) { // Store a pointer to this wrapper in the underlying instance, so that we // never create a second wrapper for the same underlying instance. Also, // specify a callback that will tell us when it's time to delete this C++ // wrapper instance: if(object) { if(!g_object_get_qdata(object, Glib::quark_)) { #ifdef DEF_DEBUG_REFCOUNTING g_warning("ObjectBase::_set_current_wrapper: g_signal_connect (destroy_notify_callback_)\n"); g_warning(" type=%s\n", G_OBJECT_TYPE_NAME(object)); #endif g_signal_connect(G_OBJECT(object), "destroy", G_CALLBACK(tmp_on_destroyed), this); g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_); } else { g_warning("This object, of type %s, already has a wrapper.\n" "You should use wrap() instead of a constructor.", G_OBJECT_TYPE_NAME(object)); } } else { #ifdef DEF_DEBUG_REFCOUNTING g_warning("ObjectBase::_set_current_wrapper: object is NULL\n"); #endif } } ##################################################################
Created attachment 17764 [details] gtk_dialog_leak.txt
:-( But now the GTk::Dialog is not destroyed: See: http://bugzilla.gnome.org/showattachment.cgi?attach_id=17764
Widget_Class::dispose_vfunc_callback is called for Gtk::Dialog, but the Dialog is not deleted?
Created attachment 17765 [details] current_test_program.txt
Just added my current test program for verification. :-)
What does the reinterpret_cast<GObjectClass*>(klass)->dispose = &dispose_vfunc_callback; inside void Widget_Class::class_init_function(void* g_class, void* class_data) actually cause? It seems to oberwrite the class->dispose = g_object_real_dispose; inside g_object_do_class_init (GObjectClass *class) What is the result of that?
Actually the MyDialog object must have been destroyed. It guaranteed by C++. I will create a dtor with debug-output to verify that. (Tomorrow) ############################### void on_button_clicked() { MyDialog d; int res = d.run(); } ###############################
I didn't see the "gtk_vbox_new" inside the valgrind output. Now it seems that the GtkVBox is not destroyed.
Interesting. I think that we had an extra little hack in gtkmm 2.0 that did a gtk_signal_connect() like you suggest that we should always do. grepping the tarball might confirm that. Maybe it was useful in more than just a special case. We simplified it for gtkmm 2.2, I think. Here is a very simple C test case that seems to show that the qdata callback is never called. It's confusing, because I'm sure it works sometimes in gtkmm. I need to check with the GTK+ mailing list that there is no error in this simple test case (gtk_qdata_callback.c).
Created attachment 17788 [details] gtk_qdata_callback.c
re the reinterpret_cast<GObjectClass*>(klass)->dispose = &dispose_vfunc_callback;: gtkmm has "derived" GObject "klasses" in which we set our gtkmm callbacks. Our gtkmm callbacks then call the original GTK+ callbacks in the original base "klasses", after doing anything special for gtkmm. You should see this if you explore the callback functions in gtkmm. It's intestersting, but I doubt it's relevant to this bug. As for your other test cases/problems, I'm not sure what the end result or question is now. I still want to investigate the simple qdata callback test case and replace it with a g_signal_connect() if necessary. It's good that you have tried that a bit already. But when we do it we would probably only want to use one callback, not both.
Is that qdata really a callback. I understood that it just stores a pointer?
Yes, the 4th parameter is a callback: http://developer.gnome.org/doc/API/2.0/gobject/gobject-The-Base- Object-Type.html#g-object-set-qdata-full
> Yes, the 4th parameter is a callback When is it supposed to be executed? (Inside what function?) Is it done automatically on object destruction? If yes, on what layer? - glib - gobject - gtk - glibmm - gtkmm > As for your other test cases/problems, > I'm not sure what the end result or question is now. The g_signal_connect causes the Gtk::VBox to be destroyed, but something created by gtk_vbox_new is not cleaned up.
Docu for g_object_set_data_full: Like g_object_set_data() except it adds notification for when the association is destroyed, either by setting it to a different value or when the object is destroyed. Docu for g_object_unref: Decreases the reference count if object. When its reference count drops to 0, the object is finalized (i.e. its memory is freed). There is also a function pointer "GObjectFinalizeFunc" but I dont know who sets it?
#################################################################### Murray, you wrote on 2003-06-24 08:09: Yes, I would expect anything from Glib::wrap() to be manage()ed. The manage() just means that the lifetime will be controlled by the GTK+ container, as per normal, not by anything in C++. The manange you are thalking about is not the Gtk::manage(which is really a Sigc++::manage), or? If so, why does the Gtk::VBox_Class::wrap_new() contains a Gtk::manage() of the result pointer? ####################################################################
Let's just wait to hear what the glib developers say in reply to my email about the gtk_qdata_callback.c test case.
>> Yes, I would expect anything from Glib::wrap() to be manage()ed.If > so, why does the Gtk::VBox_Class::wrap_new() contains a Gtk::manage() of the result pointer? So that it is manage()d, I suppose. I don't see any inconsistency here.
Created attachment 17792 [details] gtk_qdata_callback_with_ref.txt
Check my new attachment http://bugzilla.gnome.org/showattachment.cgi?attach_id=17792 There is again the refcount of 3 and I would bet that this is the problem.
Murray: What versions of gtk+ are you using? (I assume you use the most current version of gtkmm?)
Created attachment 17794 [details] gtk_qdata_callback_with_ref_out.txt
Created attachment 17797 [details] gtk_qdata_callback_with_ref_out2.txt
Created attachment 17798 [details] gtk_qdata_callback_with_ref_out3.txt
There is one reference too much. So the on_object_qdata_destroyed can not be called. See http://bugzilla.gnome.org/showattachment.cgi?attach_id=17798
Created attachment 17799 [details] gtk_qdata_har1.txt
Created attachment 17800 [details] gtk_qdata_har1_out.txt
I added an extra "gtk_object_unref" after "gtk_widget_destroy" and the result is: (main:16157): Gtk-WARNING **: A floating object was finalized. This means that someone called g_object_unref() on an object that had only a floating reference; the initial floating reference is not owned by anyone and must be removed with gtk_object_sink() after a normal reference is obtained with g_object_ref().
I am using the latest GTK+ 2.2 from cvs. This bug is getting really hard to read. Please try to reduce the unnecessary comments/attachments. But I don't want to reduce your enthusiasm.
I hope I am not writing too much, but this might be interesting: When I replace the gtk_button_new with other functions the following is the result: gtk_dialog_new - on_object_qdata_destroyed is called and no memory leak gtk_button_new - on_object_qdata_destroyed is NOT called and no memory leak (???) gtk_vbox_new - on_object_qdata_destroyed is NOT called and memory leak (!!!)
I am playing with using the "destroy" signal for GtkObjects (It does not exist in GObjects, but I think we don't have the problem there). It needs a little more work, because we need to check whether the object is a GtkObject, or if it has the "destroy" signal, before connecting that signal. The last bits of data that seem to be leaked might be explained by this: http://www.gtk.org/faq/#AEN663 But in general, it would be best now to wait for me to complete the fix. Thanks for your help.
As the GtkVBox is part of the GtkDialog, it should not be floating anymore. (I will verify that). So I assume, the Dialog does a - gtk_vbox_new - g_object_ref - (g_object_sink) - g_object_unref - gtk_widget_destroy And the qdata callback should be executed, right? It is only not executed, if some other thing did a g_object_ref on it, right? So who did it?
Murray: I think the key to the problem is the else part inside Object::_init_unmanage because it does a g_object_ref on that GtkVBox which is never ever unref'd. And that is the reason for not calling the qdata callback. I would say, either the g_object_ref needs to be removed or there must be some kind of 2-stage destroy process in gtkmm also Something like that: - leave the g_object_ref inside Object::_init_unmanage as it is - Add a g_signal_connect("destroy") for a new method that does a g_object_unref I think that would be the cleanest way. After all: Sorry that I was writing hundreds of comments and opening an unneccessary BugReport in GTK+.
Hmm, that is not the solution that I expect. Can you confirm it by a) Verifying it by using the debug output - that should show every ref and unref and other lifecycle calls. b) Verifying that it is a problem by modifying the C test case to do the same things. ?
Murray: Forget it, it (2 stage destroy) did not work.
Created attachment 17924 [details] 2step_destroy.txt
Murry: check the 2step_destroy.txt (C/Gkt+ Test case) which actually works :-) I tried modifiying the gtkmm source itself but obviously I did something wrong, because it did not work.
Created attachment 17925 [details] 2step_destroy.txt
When I am trying to add the 2step destroy directly to gtkmm using that g_signal_connect for "destroy" I get a floating object of type GtkStyle and later - GLib-GObject-WARNING **: instance of invalid non-instantiatable type `<invalid>' - GLib-GObject-CRITICAL **: file gsignal.c: line 1736 (g_signal_handlers_destroy): assertion `G_TYPE_CHECK_INSTANCE (instance)' failed - GLib-GObject-WARNING **: gobject.c:1313 g_object_unref: (null)(0x808b7d0) for the following source (the orginal test_simpler.cc) http://bugzilla.gnome.org/showattachment.cgi?attach_id=17543 I don't know how to proceed....
Created attachment 17949 [details] [review] gtk_qdata_vbox_callback.c
I think we are on the wrong track. My C example was not a good test case, but gtk_qdata_vbox_callback.c is, because it deals with the vbox when it is in a container, as Owen Taylor suggested in his email earlier. We need to find out why the qdata callback is caleld in this C example, but not in the C++ version.
That is an easy question: It is not called in C++, because inside Object::_init_unmanage (of VBox) has a g_object_ref called. And the qdata callback is only called if no reference is left anymore. (All g_object_ref must have a related g_object_unref) The basic problem seems to be some confusion about two different cases: - The C++ object controls the lifetime of the related C object (the normal case) - The C object controls the lifetime of the related C++ object (the case if a C sub-widget is wrapped, e.g. the VBox of a dialog)
So, we need to check exactly what is the refcount of the vbox _before_ it is destroyed in the C example, and before it is destroyed in the C++ example. Maybe we just need to do an extra unref before destroying it - but we need to check that first.
> So, we need to check exactly what is the refcount of the vbox _before_ it is destroyed in the C example It's 1 in the C example and 2 in the C++ example. > It is not called in C++, because inside Object::_init_unmanage (of > VBox) has a g_object_ref called. Yes, and that's probably not necessary. But removing it gives us this error, as you found: (main:16157): Gtk-WARNING **: A floating object was finalized. This means that someone called g_object_unref() on an object that had only a floating reference; the initial floating reference is not owned by anyone and must be removed with gtk_object_sink() after a normal reference is obtained with g_object_ref(). I am currently investigating why this happens. As far as I can tell, after removing that ref from _init_unmanage(), gtkmm never refs or derefs the vbox. I also noticed that _init_unmanage() sets _referenced always, but it should be false for widgets with Glib::wrap(). But fixing it does not seem to make a difference.
I think I have a simple patch for this. I'll upload it later when I find a suitable connection.
Hmm, I caused a crash on application close. But I will get there.
OK, please try this patch (gtkmm_leakfix.patch) against cvs. I think I've fixed it, but I would like you to test it thoroughly.
Created attachment 18197 [details] [review] gtkmm_leakfix.patch
Is there a patch against the official gtkmm 2.2.3? I assume not?
Not from me. It should be easier to regenerate everything with a cvs checkout anyway, when you can get anoncvs to work.
We tested the current cvs-version (which includes the leak-fix) and it looks good to us. We did some further tests if something else is influenced, but we could not find something. So I think the CVS version could be a good gtkmm 2.2.4 :-)
This has been applied. I need to merge it into gtkmm 2.4 also.
This is now in gtkmm 2.4 too.