in reply to Re: Re: Re: Re: Memory leak when using hash 'references'
in thread Memory leak when using hash 'references'
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$/}
|
|---|