Hi all, I'm creating a GUI that includes the ability to add or remove 'sections' of text. I'm using Glade, so each section is created on the fly by loading a section of the Glade spec and pulling widgets out of it. I keep track of the glade objects and the callback objects they refer to, and when a section is deleted those section widgets are destroyed. Note that I have to use a Table to add section parts into rather than a VBox because the right hand side of each section has to line up with a widget (in the test case below a Label) exactly. In the real code this widget is a character-marked ruler. Unfortunately, while it works nicely as far as the user is concerned, it seems a little bit of memory is leaking when a section is deleted. I've attached the Glade XML file for a test case, and below is the driving code. If you run it and then hit the 'add' button 5 times, the memory usage goes up as expected. If you then delete all 5 and hit add another 5 times, memory usage goes up again - in smaller steps than the first time. I was expecting that if you created X sections you could delete/add to your heart's content and as long as the section count never exceeded X you'd never use more memory. Am I incorrect in this assumption or am I forgetting something in my code? TIA, MB ----- START CODE ----- use strict; use Gtk2 -init; use Gtk2::GladeXML; my $GLADE_FILE = '/path/to/test.glade'; my @sections; my $MGLADE; { package SECTIONCALLBACKS; sub new { bless({}) } sub delete { my $self = shift; my $i = $self->_find_pos; return if not defined $i; my $tbl = $MGLADE->get_widget('SectionBox'); # Do some extra destroying - not sure if this is entirely necessary my $sect = $sections[$i]; for my $child ($sect->[0]->get_widget('SectionLeft')->get_children, $sect->[0]->get_widget('SectionRight')->get_children) { $child->destroy; } $tbl->remove($sect->[0]->get_widget('SectionLeft')); $tbl->remove($sect->[0]->get_widget('SectionRight')); $sect->[0]->DESTROY; # Remove this entry from @sections splice(@sections, $i, 1); # Re-pack subsequent items so no gaps in table... for my $j ($i..scalar(@sections) - 1) { my ($l, $r) = ($sections[$j][0]->get_widget('SectionLeft'), $sections[$j][0]->get_widget('SectionRight')); $tbl->remove($l); $tbl->remove($r); $tbl->attach($l, 0, 1, $j + 1, $j + 2, [qw/fill/], [qw/fill/], 0, 0); $tbl->attach($r, 1, 2, $j + 1, $j + 2, [qw/fill expand/], [qw/fill expand/], 0, 0); } } sub _find_pos { my $self = shift; for my $i (0..scalar(@sections) - 1) { return $i if $sections[$i][1] eq $self; } return undef; } } { package MAINCALLBACKS; sub new { bless({}) } sub add { my $self = shift; my $nglade = Gtk2::GladeXML->new($GLADE_FILE, 'SectionTable'); my $ncb = SECTIONCALLBACKS->new; $nglade->signal_autoconnect_from_package($ncb); my $tab = $MGLADE->get_widget('SectionBox'); my ($oldparent, $left, $right) = ($nglade->get_widget('SectionTable'), $nglade->get_widget('SectionLeft'), $nglade->get_widget('SectionRight')); $oldparent->remove($left); $oldparent->remove($right); $oldparent->destroy; my $top = scalar(@sections) + 1; # Plus one due to the header label $tab->attach($left, 0, 1, $top, $top + 1, [qw/fill/], [qw/fill/], 0, 0); $tab->attach($right, 1, 2, $top, $top + 1, [qw/fill expand/], [qw/fill expand/], 0, 0); push @sections, [$nglade, $ncb]; } sub quit { exit } } $MGLADE = Gtk2::GladeXML->new($GLADE_FILE, 'MainWindow'); $MGLADE->signal_autoconnect_from_package(MAINCALLBACKS->new); Gtk2->main;
Attachment:
test.glade
Description: Binary data