Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Who's referencing my variables?

by RutgerVos (Initiate)
on Apr 01, 2014 at 09:51 UTC ( #1080516=perlquestion: print w/replies, xml ) Need Help??
RutgerVos has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

in a fairly large set of modules I am noticing some objects not getting cleaned up when they go out of scope: circular references. As these objects get passed around quite a lot it is hard to pin down where this is happening. What would be a way to find out who's referencing whom?

Thinking this through a little bit I imagine the way would be to traverse the symbol table(s) and look at package variables that might be referencing the objects. Can somebody give me a hint how I would probe 'my' variables that live inside packages? As far as I can tell, %Foo::Bar:: gives me subroutines and our variables but not 'my' variables. I'm sure there's a way around that ;-)



Replies are listed 'Best First'.
Re: Who's referencing my variables?
by LanX (Bishop) on Apr 01, 2014 at 10:02 UTC
    My variables don't live within packages!

    You can use Devel::Peek to check reference counts of lexicals and PadWalker to hunt them down in closures.

    HTH! :)

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      I'm afraid my original post wasn't entirely clear. Consider the following code:
      package Foo; my @objects; sub new { my $self = bless {}, shift; push @objects, $self; return $self; } sub DESTROY { print "bye bye" } package main; { my $foo = Foo->new; } ETERNITY: while(1) { # DESTROY is NOT called yet. }
      When you run this, "bye bye" is not printed while we're waiting inside ETERNITY because @Foo::objects still holds a reference to $foo, even though its instantiation happened inside a scope we've since left.

      What I want to be able to do is to discover whether and where similar @Foo::objects-like data structures exist in a large code base. So I need to walk the symbol tables and probe what's there. How do I find such symbols? Can I?

        Hi RutgerVos: I assume you posted the code shown above.

        When you write and show us code that demonstrates some painful consequence and then ask "How can I avoid this pain?", the obvious, simple and complete answer is "Don't do that!"

        I suppose what you really mean is that other people, users of your code, are indulging nasty, unclean practices that are the source of the pain, such as exemplified by tobyink here. In this case, the only true solution is code review: go around and whack everyone's hand with a ruler until they stop doing the nasty. If a ruler doesn't work, use a hatchet. Others have pointed out tools to aid the review process, but you must ultimately persuade others not to do Bad Things with your code. Other than Good Practice, I'm not aware of any procedure in Perl that will 'armor' a reference, object or otherwise, against being circularized or otherwise given an infinite lifetime.

        Here is how you should have written that
        our @objecgts; ## @Foo::objects ... push @objects, weaken $object;

        If you're going to do things the fudgy way, do it the easy fudgy way

Re: Who's referencing my variables?
by tobyink (Abbot) on Apr 01, 2014 at 12:19 UTC

    They are probably not being referenced from the synbol table, but rather they're being referenced from other lexical variables.

    use 5.010; use strict; use warnings; END { say "Finished script; start of global clean-up" }; { package noisy; use overload q[""] => sub { $_[0][0] }; sub DESTROY { say "$_[0] is being cleaned up" } } # Simple { my $a = bless ['$a'], "noisy"; say "defined $a"; } # $a gets cleaned up # Linear refs { my $b = bless ['$b'], "noisy"; my $c = bless ['$c', $b], "noisy"; # refers to $b my $d = bless ['$d', $c], "noisy"; # refers to $c say "defined $b, $c, and $d"; } # $b, $c, $d get cleaned up # Circular refs { my $e = bless ['$e'], "noisy"; # we'll make this refer to $g soon +! my $f = bless ['$f', $e], "noisy"; # refers to $e my $g = bless ['$g', $f], "noisy"; # refers to $f push @$e, $g; # create reference cycle say "defined $e, $f, and $g"; } # $e, $f, $g cannot be cleaned up
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: Who's referencing my variables?
by Athanasius (Chancellor) on Apr 01, 2014 at 12:20 UTC
Re: Who's referencing my variables?
by Anonymous Monk on Apr 01, 2014 at 09:55 UTC

    I've got a copy/paste about memory leaks

Re: Who's referencing my variables?
by Anonymous Monk on Apr 01, 2014 at 13:16 UTC
    Also Test::Memory::Cycle, which of course uses Devel::Cycle. These sorts of problems usually can't be found by static evaluation of the code: you must let it run for a while, then test for cycles, then sleuth it all out as to why.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1080516]
Approved by Happy-the-monk
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2018-02-18 01:54 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (250 votes). Check out past polls.