Devel::FindRef - Was referenziert diese Variable?

Veröffentlicht von Thomas Fahle am (Permalink)

Häufig steht man vor der Frage, wo genau eine Variable (oder allgemein ein Perl-Wert) referenziert wird.

Devel::FindRef von Marc Lehmann ist ein kleines Modul, mit dem man exakt herausfinden kann, wo eine bestimmte Variable referenziert wird, ob es einen Referenz-Zyklus gibt, oder welche closure den Wert noch referenziert.

Marc Lehmann hat Devel::FindRef in einem Lightning Talk auf dem 11. Deutschen Perl-Workshop in Frankfurt/Main vorgestellt.

Einfaches Beispiel

#!/usr/bin/perl 
use strict;
use warnings;

use Devel::FindRef;
                         
    # Die Variable, die untersucht werden soll
our $var            = 'hi there';

    # Ein paar Referenzen auf diese Variable
my $global_my       = \$var;
our %global_hash    = ( key1 => \$var );
our $global_hashref = { key2 => \$var };


testsub();
                           
sub testsub {             
      my $testsub_local = $global_hashref;
	  print "Track für \$var '$var':\n";
      print Devel::FindRef::track \$var;
}                             

Das Programm erzeugt folgende Ausgabe:

Track für $var 'hi there':
SCALAR(0x8169fe8) [refcount 5] is
+- in the global $main::var.
+- referenced by REF(0x8169fa8) [refcount 1], which is
|  in the lexical '$global_my' in CODE(0x8155318) [refcount 2], which is
|     +- the containing scope for CODE(0x81a5468) [refcount 3], which is
|     |  in the global &main::testsub.
|     +- the main body of the program.
+- referenced by REF(0x8169f28) [refcount 1], which is
|  in the member 'key2' of HASH(0x81550b8) [refcount 2], which is
|     +- referenced by REF(0x81a54c8) [refcount 1], which is
|     |  in the lexical '$testsub_local' in CODE(0x81a5468) [refcount 3], which was seen before.
|     +- referenced by REF(0x81a5168) [refcount 1], which is
|        in the global $main::global_hashref.
+- referenced by REF(0x8155308) [refcount 1], which is
|  in the member 'key1' of HASH(0x816a368) [refcount 1], which is
|     in the global %main::global_hash.
+- referenced by REF(0x81551d8) [refcount 1], which is
   a temporary on the stack.

Die Ausgabe muss man sich anfangs wohl zwei- oder dreimal anschauen, danach wird es besser.

Beispiel: Verwendung von closures und weaken

#!/usr/bin/perl 
use strict;
use warnings;


use Devel::FindRef;
use Scalar::Util;
                         
our $var            = 'hi there';
my $global_my       = \$var;
our %global_hash    = ( key1 => \$var);
our $global_hashref = { key2 => \$var };
                           
sub testsub {             
      my $testsub_local = $global_hashref;
	  print "Track fuer \$var '$var':\n";
      print Devel::FindRef::track \$var;
}                             


my $closure = sub {
      my $closure_var = \$_[0];
      Scalar::Util::weaken (my $weak_ref = \$var);
      testsub();
   };

$closure->($var);

Das Programm erzeugt folgende Ausgabe:

Track fuer $var 'hi there':
SCALAR(0x8169f58) [refcount 6] is
+- referenced by REF(0x81a5640) [refcount 1], which is
|  in the lexical '$closure_var' in CODE(0x81a5600) [refcount 4], which is
|     +- the closure created at f2.pl:22.
|     +- referenced by REF(0x81a5440) [refcount 1], which is
|     |  in the lexical '$closure' in CODE(0x8155318) [refcount 2], which is
|     |     +- the containing scope for CODE(0x81a5460) [refcount 3], which is
|     |     |  in the global &main::testsub.
|     |     +- the main body of the program.
|     +- in the lexical '&' in CODE(0x8155318) [refcount 2], which was seen before.
+- referenced by REF(0x816a008) [refcount 1], which is
|  in the lexical '$global_my' in CODE(0x8155318) [refcount 2], which was seen before.
+- in the global $main::var.
+- referenced by REF(0x8169f28) [refcount 1], which is
|  in the member 'key2' of HASH(0x81550b8) [refcount 2], which is
|     +- referenced by REF(0x81a54d0) [refcount 1], which is
|     |  in the lexical '$testsub_local' in CODE(0x81a5460) [refcount 3], which was seen before.
|     +- referenced by REF(0x81a51a0) [refcount 1], which is
|        in the global $main::global_hashref.
+- referenced by REF(0x8155308) [refcount 1], which is
|  in the member 'key1' of HASH(0x816a368) [refcount 1], which is
|     in the global %main::global_hash.
+- referenced by REF(0x81551d8) [refcount 1], which is
   a temporary on the stack.

Cool!

Siehe auch:

Weitere Posts