in reply to Re: Re: Memory leak when using hash 'references'
in thread Memory leak when using hash 'references'

I'm not sure if this is the case, but don't forget that Perl doesn't destroy anything until all references to it are either destroyed or undefed.

To free up the memory associated with the data, and release it back to Perl, you need to make sure that you also set the original variables that store the data to be undef, and ensure you have no other references to that item that could be keeping it defined.

Just thinking about scoping, both of the variables you undef in your subs are localised with my anyway, and hence will be automatically destroyed when that sub finishes executing.

I can't really say any more than that without seeing more code - I'd suggest first to check for references to the data that could be keeping it defined in memory.

Hope that helps ..
-- Foxcub
A friend is someone who can see straight through you, yet still enjoy the view. (Anon)

Replies are listed 'Best First'.
Re: Re: Re: Re: Memory leak when using hash 'references'
by sureshr (Beadle) on Mar 13, 2003 at 15:45 UTC
    Thank you Foxcub, I will revisit all my code to see if there are any dangling references (seems like I could no longer rely on 'my' to free up memory for me, in case of references) and undef them.
    -sureshr

      Additionally, be aware that Perl does not do lisp-style garbage collection; it just counts references. Consequently, if your data structure has any circular references (such as child objects that keep a reference back to their parents), letting them pass out of scope and clearing your variables that point to the whole structure won't do the trick. You have to walk the structure and undo the links from both ends. For example...

      { # WRONG: my @queue = (); foreach (@_) { my ($a, $b, $ch) = /(\d*)[:]([^:])[:](.*?)$/; my %parent = (a => $a, b => $b); my @children = map { my ($d, $e, $f) = split /:/, $_; my %c = (d=>$d, e=>$e, f=>$f, p=>\%parent); \%c; } split /,/, $ch; $parent{children}=\@children; push @queue, \%parent; } while (pop @queue) { do_stuff($_); } # The item that was popped off the queue now is out of scope, # but its children point back to it, so it stays in memory. } # Now the whole queue is out of scope, but the items formerly # in it are still in memory, even now -- and there's no way # to get back to them and free them, because you've lost # track of all the references, even though they still exist. { # BETTER: my @queue = (); foreach (@_) { my ($a, $b, $ch) = /(\d*)[:]([^:])[:](.*?)$/; my %parent = (a => $a, b => $b); my @children = map { my ($d, $e, $f) = split /:/, $_; my %c = (d=>$d, e=>$e, f=>$f, p=>\%parent); \%c; } split /,/, $ch; $parent{children}=\@children; push @queue, \%parent; } while (pop @queue) { do_stuff($_); foreach (@{$$_{children}}) { $$_{p}=undef; # child no longer has reference to parent. } undef $_; # Now there are zero references to the item, # so it does go away, taking with it its # ch key and the anon array that is its # value, which drops the refcount to each # element of that array to zero, causing # them to be freed, which in turn frees # each of the children -- I think. } }

      This is only your problem if you have any structures that point to eachother possibly forming a cycle of references. (The simplest case is pairs of mutually- referenced objects as above, but cases where a holds a ref to b that holds a ref to c that holds a ref to d that holds a ref to a will do the same thing.)


      for(unpack("C*",'GGGG?GGGG?O__\?WccW?{GCw?Wcc{?Wcc~?Wcc{?~cc' .'W?')){$j=$_-63;++$a;for$p(0..7){$h[$p][$a]=$j%2;$j/=2}}for$ p(0..7){for$a(1..45){$_=($h[$p-1][$a])?'#':' ';print}print$/}