After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 114568 - Memory leak in Dialog::get_vbox() and get_action_area ()
Memory leak in Dialog::get_vbox() and get_action_area ()
Status: RESOLVED FIXED
Product: gtkmm
Classification: Bindings
Component: general
2.4
Other Linux
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on: 116014
Blocks:
 
 
Reported: 2003-06-06 14:06 UTC by Harald Hopfes
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Source-code of test program. (966 bytes, text/plain)
2003-06-06 14:14 UTC, Harald Hopfes
  Details
Valgrind output of 1 open/close action (15.22 KB, text/plain)
2003-06-06 14:15 UTC, Harald Hopfes
  Details
Valgrind output of 10 open/close action (15.22 KB, text/plain)
2003-06-06 14:16 UTC, Harald Hopfes
  Details
test_simpler.cc (567 bytes, text/plain)
2003-06-15 16:25 UTC, Murray Cumming
  Details
Valgrind output of test_simpler.cc (including valgrind cmd-line args) (11.18 KB, text/plain)
2003-06-23 10:20 UTC, Harald Hopfes
  Details
test_simpler_gcc3_3.valgrind.txt (10.13 KB, text/plain)
2003-06-23 13:52 UTC, Harald Hopfes
  Details
test_combo.cc (shows the problem for ComboBox also) (584 bytes, text/plain)
2003-06-24 12:32 UTC, Harald Hopfes
  Details
New test_combo.cc (572 bytes, text/plain)
2003-06-24 12:36 UTC, Harald Hopfes
  Details
gtk_plus_destroy_src.txt (812 bytes, text/plain)
2003-06-24 14:12 UTC, Harald Hopfes
  Details
gtk_plus_destroy_out.txt (4.49 KB, text/plain)
2003-06-24 14:16 UTC, Harald Hopfes
  Details
gtk_plus_destroy_src2.txt (930 bytes, text/plain)
2003-06-24 14:31 UTC, Harald Hopfes
  Details
gtk_plus_destroy_out2.txt (4.70 KB, text/plain)
2003-06-24 14:32 UTC, Harald Hopfes
  Details
g_object_qdata_out.txt (21.51 KB, text/plain)
2003-06-25 16:37 UTC, Harald Hopfes
  Details
gtk_dialog_leak.txt (2.92 KB, text/plain)
2003-06-25 17:47 UTC, Harald Hopfes
  Details
current_test_program.txt (1.14 KB, text/plain)
2003-06-25 17:59 UTC, Harald Hopfes
  Details
gtk_qdata_callback.c (1.04 KB, text/plain)
2003-06-26 06:50 UTC, Murray Cumming
  Details
gtk_qdata_callback_with_ref.txt (1.25 KB, text/plain)
2003-06-26 10:20 UTC, Harald Hopfes
  Details
gtk_qdata_callback_with_ref_out.txt (1.51 KB, text/plain)
2003-06-26 10:46 UTC, Harald Hopfes
  Details
gtk_qdata_callback_with_ref_out2.txt (1.58 KB, text/plain)
2003-06-26 10:49 UTC, Harald Hopfes
  Details
gtk_qdata_callback_with_ref_out3.txt (1.46 KB, text/plain)
2003-06-26 11:00 UTC, Harald Hopfes
  Details
gtk_qdata_har1.txt (1.35 KB, text/plain)
2003-06-26 11:13 UTC, Harald Hopfes
  Details
gtk_qdata_har1_out.txt (3.02 KB, text/plain)
2003-06-26 11:14 UTC, Harald Hopfes
  Details
2step_destroy.txt (1.53 KB, text/plain)
2003-06-30 14:06 UTC, Harald Hopfes
  Details
2step_destroy.txt (1.49 KB, text/plain)
2003-06-30 14:14 UTC, Harald Hopfes
  Details
gtk_qdata_vbox_callback.c (1.22 KB, patch)
2003-07-01 06:24 UTC, Murray Cumming
none Details | Review
gtkmm_leakfix.patch (16.84 KB, patch)
2003-07-10 16:12 UTC, Murray Cumming
none Details | Review

Description Harald Hopfes 2003-06-06 14:06:33 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
Comment 1 Harald Hopfes 2003-06-06 14:14:22 UTC
Created attachment 17228 [details]
Source-code of test program.
Comment 2 Harald Hopfes 2003-06-06 14:15:33 UTC
Created attachment 17229 [details]
Valgrind output of 1 open/close action
Comment 3 Harald Hopfes 2003-06-06 14:16:07 UTC
Created attachment 17230 [details]
Valgrind output of 10 open/close action
Comment 4 Murray Cumming 2003-06-13 06:47:00 UTC
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.

Comment 5 Murray Cumming 2003-06-15 16:25:16 UTC
Created attachment 17543 [details]
test_simpler.cc
Comment 6 Murray Cumming 2003-06-15 16:26:46 UTC
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?
Comment 7 Harald Hopfes 2003-06-23 10:20:11 UTC
Created attachment 17702 [details]
Valgrind output of test_simpler.cc (including valgrind cmd-line args)
Comment 8 Harald Hopfes 2003-06-23 11:05:20 UTC
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
Comment 9 Harald Hopfes 2003-06-23 11:07:30 UTC
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....
Comment 10 Murray Cumming 2003-06-23 11:26:15 UTC
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.
Comment 11 Harald Hopfes 2003-06-23 11:45:53 UTC
Yes, check the new Attachment.
There you can see that the problem remains.
Comment 12 Harald Hopfes 2003-06-23 12:05:05 UTC
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?
Comment 13 Harald Hopfes 2003-06-23 12:10:33 UTC
I will check if the problem remains with gcc 3.3.
Comment 14 Harald Hopfes 2003-06-23 13:52:22 UTC
Created attachment 17705 [details]
test_simpler_gcc3_3.valgrind.txt
Comment 15 Harald Hopfes 2003-06-23 13:53:26 UTC
The problem remains with gcc-3.3 also.
Comment 16 Harald Hopfes 2003-06-23 13:59:02 UTC
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
Comment 17 Murray Cumming 2003-06-24 08:24:49 UTC
OK, I will investigate when I get a chance. I was not using the same
valgrind command.

But you are capable of investigating yourself.
Comment 18 Harald Hopfes 2003-06-24 10:17:40 UTC
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???
Comment 19 Harald Hopfes 2003-06-24 11:04:01 UTC
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.
Comment 20 Harald Hopfes 2003-06-24 11:42:28 UTC
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??
Comment 21 Harald Hopfes 2003-06-24 11:46:23 UTC
The phrase "managed object of the class Gtk::Dialog" should be 
"managed object of the object of class Gtk::Dialog"
(to prevent confusion)
Comment 22 Harald Hopfes 2003-06-24 11:49:27 UTC
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.

Comment 23 Murray Cumming 2003-06-24 12:09:43 UTC
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.
Comment 24 Murray Cumming 2003-06-24 12:10:50 UTC
Yes, destroying a C++ instance always destroys the underlying C 
instance. The lifetimes of widgets and their C++ wrappers should be 
very tightly bound.
Comment 25 Harald Hopfes 2003-06-24 12:32:16 UTC
Created attachment 17727 [details]
test_combo.cc (shows the problem for ComboBox also)
Comment 26 Harald Hopfes 2003-06-24 12:34:27 UTC
Forgot to replace the ToggleButton with Button in the test_combo.cc 
example.
Comment 27 Harald Hopfes 2003-06-24 12:36:27 UTC
Created attachment 17728 [details]
New test_combo.cc
Comment 28 Harald Hopfes 2003-06-24 12:38:31 UTC
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.
Comment 29 Harald Hopfes 2003-06-24 12:45:53 UTC
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?
Comment 30 Harald Hopfes 2003-06-24 12:49:08 UTC
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)
Comment 31 Harald Hopfes 2003-06-24 12:52:02 UTC
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.
Comment 32 Murray Cumming 2003-06-24 12:54:20 UTC
> 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.
Comment 33 Harald Hopfes 2003-06-24 14:12:53 UTC
Created attachment 17730 [details]
gtk_plus_destroy_src.txt
Comment 34 Harald Hopfes 2003-06-24 14:16:29 UTC
Created attachment 17731 [details]
gtk_plus_destroy_out.txt
Comment 35 Harald Hopfes 2003-06-24 14:22:07 UTC
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
Comment 36 Harald Hopfes 2003-06-24 14:31:55 UTC
Created attachment 17732 [details]
gtk_plus_destroy_src2.txt
Comment 37 Harald Hopfes 2003-06-24 14:32:33 UTC
Created attachment 17733 [details]
gtk_plus_destroy_out2.txt
Comment 38 Murray Cumming 2003-06-24 14:37:57 UTC
> 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.
Comment 39 Murray Cumming 2003-06-24 14:42:18 UTC
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.
Comment 40 Harald Hopfes 2003-06-24 15:22:48 UTC
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?
Comment 41 Murray Cumming 2003-06-24 15:24:32 UTC
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.
Comment 42 Harald Hopfes 2003-06-24 16:27:55 UTC
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.
Comment 43 Harald Hopfes 2003-06-24 16:32:09 UTC
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?
Comment 44 Murray Cumming 2003-06-24 16:42:12 UTC
> 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.
Comment 45 Harald Hopfes 2003-06-24 17:08:12 UTC
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.
Comment 46 Harald Hopfes 2003-06-24 18:10:11 UTC
gtk_object_destroy for GtkVBox is called just before my Testprogram 
displays "on_vbox_destroyed"
Comment 47 Harald Hopfes 2003-06-24 18:11:56 UTC
And after displaying "on_vbox_destroyed", the function 
gtk_container_destroy gets called for GtkVBox.
Comment 48 Harald Hopfes 2003-06-24 18:15:41 UTC
I correct myself:

  Gtk::Widget_Class::dispose_vfunc_callback()

is called, but only for the gtkmm__GtkDialog.
Comment 49 Harald Hopfes 2003-06-24 18:36:24 UTC
Also gtk_object_real_destroy gets called for GtkVBox.
Comment 50 Harald Hopfes 2003-06-24 18:43:12 UTC
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?
Comment 51 Harald Hopfes 2003-06-24 18:48:20 UTC
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

Comment 52 Murray Cumming 2003-06-25 07:24:23 UTC
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".
Comment 53 Harald Hopfes 2003-06-25 08:06:19 UTC
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? 
Comment 54 Murray Cumming 2003-06-25 08:31:28 UTC
Hmm, I think this bugs had that problem:
http://bugzilla.gnome.org/show_bug.cgi?id=111084
Comment 55 Harald Hopfes 2003-06-25 09:13:45 UTC
I found another maybe relevant bug 
http://bugzilla.gnome.org/show_bug.cgi?id=91404 
Comment 56 Harald Hopfes 2003-06-25 09:50:48 UTC
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?
Comment 57 Murray Cumming 2003-06-25 10:00:04 UTC
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
Comment 58 Harald Hopfes 2003-06-25 16:23:49 UTC
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
Comment 59 Harald Hopfes 2003-06-25 16:37:00 UTC
Created attachment 17759 [details]
g_object_qdata_out.txt
Comment 60 Harald Hopfes 2003-06-25 16:48:59 UTC
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+?
Comment 61 Harald Hopfes 2003-06-25 16:51:52 UTC
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.
Comment 62 Harald Hopfes 2003-06-25 16:58:15 UTC
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"
Comment 63 Murray Cumming 2003-06-25 17:11:53 UTC
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.
Comment 64 Harald Hopfes 2003-06-25 17:26:27 UTC
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.
Comment 65 Harald Hopfes 2003-06-25 17:33:04 UTC
I will try that "g_signal_connect" once,
if it doesn't work I'll give up.
Comment 66 Harald Hopfes 2003-06-25 17:43:20 UTC
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
    }
}

##################################################################

Comment 67 Harald Hopfes 2003-06-25 17:47:59 UTC
Created attachment 17764 [details]
gtk_dialog_leak.txt
Comment 68 Harald Hopfes 2003-06-25 17:48:50 UTC
:-(
But now the GTk::Dialog is not destroyed:

See:
http://bugzilla.gnome.org/showattachment.cgi?attach_id=17764
Comment 69 Harald Hopfes 2003-06-25 17:55:54 UTC
Widget_Class::dispose_vfunc_callback is called for Gtk::Dialog, but 
the Dialog is not deleted?

Comment 70 Harald Hopfes 2003-06-25 17:59:33 UTC
Created attachment 17765 [details]
current_test_program.txt
Comment 71 Harald Hopfes 2003-06-25 18:00:49 UTC
Just added my current test program for verification. :-)
Comment 72 Harald Hopfes 2003-06-25 18:14:00 UTC
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?
Comment 73 Harald Hopfes 2003-06-25 20:32:39 UTC
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();
  }
###############################
Comment 74 Harald Hopfes 2003-06-26 05:55:20 UTC
I didn't see the "gtk_vbox_new" inside the valgrind output. 
Now it seems that the GtkVBox is not destroyed.
Comment 75 Murray Cumming 2003-06-26 06:49:40 UTC
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).  
Comment 76 Murray Cumming 2003-06-26 06:50:23 UTC
Created attachment 17788 [details]
gtk_qdata_callback.c
Comment 77 Murray Cumming 2003-06-26 07:19:49 UTC
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.
Comment 78 Harald Hopfes 2003-06-26 09:03:28 UTC
Is that qdata really a callback. I understood that it just stores a
pointer?
Comment 79 Murray Cumming 2003-06-26 09:08:47 UTC
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
Comment 80 Harald Hopfes 2003-06-26 09:14:26 UTC
> 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.
Comment 81 Harald Hopfes 2003-06-26 09:23:07 UTC
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?
Comment 82 Harald Hopfes 2003-06-26 09:38:22 UTC
####################################################################

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?

####################################################################
Comment 83 Murray Cumming 2003-06-26 09:39:39 UTC
Let's just wait to hear what the glib developers say in reply to my 
email about the gtk_qdata_callback.c test case.
Comment 84 Murray Cumming 2003-06-26 09:41:29 UTC
>> 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.
Comment 85 Harald Hopfes 2003-06-26 10:20:04 UTC
Created attachment 17792 [details]
gtk_qdata_callback_with_ref.txt
Comment 86 Harald Hopfes 2003-06-26 10:22:15 UTC
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.
Comment 87 Harald Hopfes 2003-06-26 10:44:31 UTC
Murray: What versions of gtk+ are you using? (I assume you use the 
most current version of gtkmm?)
Comment 88 Harald Hopfes 2003-06-26 10:46:25 UTC
Created attachment 17794 [details]
gtk_qdata_callback_with_ref_out.txt
Comment 89 Harald Hopfes 2003-06-26 10:49:50 UTC
Created attachment 17797 [details]
gtk_qdata_callback_with_ref_out2.txt
Comment 90 Harald Hopfes 2003-06-26 11:00:33 UTC
Created attachment 17798 [details]
gtk_qdata_callback_with_ref_out3.txt
Comment 91 Harald Hopfes 2003-06-26 11:02:23 UTC
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
Comment 92 Harald Hopfes 2003-06-26 11:13:05 UTC
Created attachment 17799 [details]
gtk_qdata_har1.txt
Comment 93 Harald Hopfes 2003-06-26 11:14:39 UTC
Created attachment 17800 [details]
gtk_qdata_har1_out.txt
Comment 94 Harald Hopfes 2003-06-26 11:18:51 UTC
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().

Comment 95 Murray Cumming 2003-06-26 12:47:44 UTC
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.
Comment 96 Harald Hopfes 2003-06-26 14:01:15 UTC
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 (!!!)
Comment 97 Murray Cumming 2003-06-27 06:25:20 UTC
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.
Comment 98 Harald Hopfes 2003-06-27 08:31:00 UTC
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?
Comment 99 Harald Hopfes 2003-06-27 15:33:57 UTC
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+.
Comment 100 Murray Cumming 2003-06-27 15:55:14 UTC
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.
?
Comment 101 Harald Hopfes 2003-06-27 16:06:27 UTC
Murray: Forget it, it (2 stage destroy) did not work.
Comment 102 Harald Hopfes 2003-06-30 14:06:34 UTC
Created attachment 17924 [details]
2step_destroy.txt
Comment 103 Harald Hopfes 2003-06-30 14:08:45 UTC
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.
Comment 104 Harald Hopfes 2003-06-30 14:14:08 UTC
Created attachment 17925 [details]
2step_destroy.txt
Comment 105 Harald Hopfes 2003-06-30 17:07:32 UTC
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....
Comment 106 Murray Cumming 2003-07-01 06:24:59 UTC
Created attachment 17949 [details] [review]
gtk_qdata_vbox_callback.c
Comment 107 Murray Cumming 2003-07-01 06:27:02 UTC
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.
Comment 108 Harald Hopfes 2003-07-01 08:35:12 UTC
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)

Comment 109 Murray Cumming 2003-07-01 15:00:28 UTC
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. 
Comment 110 Murray Cumming 2003-07-03 06:08:22 UTC
> 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.
Comment 111 Murray Cumming 2003-07-06 13:11:36 UTC
I think I have a simple patch for this. I'll upload it later when I
find a suitable connection.
Comment 112 Murray Cumming 2003-07-09 12:08:16 UTC
Hmm, I caused a crash on application close. But I will get there.
Comment 113 Murray Cumming 2003-07-10 16:10:35 UTC
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.
Comment 114 Murray Cumming 2003-07-10 16:12:18 UTC
Created attachment 18197 [details] [review]
gtkmm_leakfix.patch
Comment 115 Harald Hopfes 2003-07-11 11:25:46 UTC
Is there a patch against the official gtkmm 2.2.3? I assume not?
Comment 116 Murray Cumming 2003-07-11 11:57:22 UTC
Not from me. It should be easier to regenerate everything with a cvs 
checkout anyway, when you can get anoncvs to work.
Comment 117 Harald Hopfes 2003-07-17 10:24:30 UTC
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 :-)
Comment 118 Murray Cumming 2003-07-18 12:29:39 UTC
This has been applied. I need to merge it into gtkmm 2.4 also.
Comment 119 Murray Cumming 2003-07-19 15:40:52 UTC
This is now in gtkmm 2.4 too.