ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Devel-FindRef/FindRef.pm
(Generate patch)

Comparing Devel-FindRef/FindRef.pm (file contents):
Revision 1.17 by root, Wed Nov 19 07:36:40 2008 UTC vs.
Revision 1.23 by root, Wed Jul 1 08:25:04 2009 UTC

5 5
6use XSLoader; 6use XSLoader;
7use Scalar::Util; 7use Scalar::Util;
8 8
9BEGIN { 9BEGIN {
10 our $VERSION = '1.31'; 10 our $VERSION = '1.42';
11 XSLoader::load __PACKAGE__, $VERSION; 11 XSLoader::load __PACKAGE__, $VERSION;
12} 12}
13 13
14=head1 NAME 14=head1 NAME
15 15
32the variables containing them. 32the variables containing them.
33 33
34For example, for this fragment: 34For example, for this fragment:
35 35
36 package Test; 36 package Test;
37
38 use Devel::FindRef;
39 use Scalar::Util;
37 40
38 our $var = "hi\n"; 41 our $var = "hi\n";
39 my $x = \$var; 42 my $global_my = \$var;
40 our %hash = (ukukey => \$var); 43 our %global_hash = (ukukey => \$var);
41 our $hash2 = {ukukey2 => \$var}; 44 our $global_hashref = { ukukey2 => \$var };
42 45
43 sub testsub { 46 sub testsub {
44 my $local = $hash2; 47 my $testsub_local = $global_hashref;
45 print Devel::FindRef::track \$var; 48 print Devel::FindRef::track \$var;
46 } 49 }
47 50
48 testsub; 51
52 my $closure = sub {
53 my $closure_var = \$_[0];
54 Scalar::Util::weaken (my $weak_ref = \$var);
55 testsub;
56 };
57
58 $closure->($var);
49 59
50The output is as follows (or similar to this, in case I forget to update 60The output is as follows (or similar to this, in case I forget to update
51the manpage after some changes): 61the manpage after some changes):
52 62
53 SCALAR(0x814ece8) is 63 SCALAR(0x7cc888) [refcount 6] is
64 +- referenced by REF(0x8abcc8) [refcount 1], which is
65 | in the lexical '$closure_var' in CODE(0x8abc50) [refcount 4], which is
66 | +- the closure created at tst:18.
67 | +- referenced by REF(0x7d3c58) [refcount 1], which is
68 | | in the lexical '$closure' in CODE(0x7ae530) [refcount 2], which is
69 | | +- the containing scope for CODE(0x8ab430) [refcount 3], which is
70 | | | in the global &Test::testsub.
71 | | +- the main body of the program.
72 | +- in the lexical '&' in CODE(0x7ae530) [refcount 2], which was seen before.
73 +- referenced by REF(0x7cc7c8) [refcount 1], which is
74 | in the lexical '$global_my' in CODE(0x7ae530) [refcount 2], which was seen before.
54 +- in the global $Test::var. 75 +- in the global $Test::var.
55 +- referenced by REF(0x814f9e4), which is 76 +- referenced by REF(0x7cc558) [refcount 1], which is
56 | in the lexical '$x' in CODE(0x814ed78), which is
57 | the containing scope for CODE(0x820c4b0), which is
58 | in the global &Test::testsub.
59 +- referenced by REF(0x814ed6c), which is
60 | in the member 'ukukey' of HASH(0x81da20c), which is 77 | in the member 'ukukey2' of HASH(0x7ae140) [refcount 2], which is
78 | +- referenced by REF(0x8abad0) [refcount 1], which is
79 | | in the lexical '$testsub_local' in CODE(0x8ab430) [refcount 3], which was seen before.
80 | +- referenced by REF(0x8ab4f0) [refcount 1], which is
81 | in the global $Test::global_hashref.
82 +- referenced by REF(0x7ae518) [refcount 1], which is
83 | in the member 'ukukey' of HASH(0x7d3bb0) [refcount 1], which is
61 | in the global %Test::hash. 84 | in the global %Test::global_hash.
62 +- referenced by REF(0x814ec28), which is 85 +- referenced by REF(0x7ae2f0) [refcount 1], which is
63 | not found anywhere I looked :( 86 a temporary on the stack.
64 +- referenced by REF(0x814eb44), which is
65 in the member 'ukukey2' of HASH(0x814f99c), which is
66 +- referenced by REF(0x820c450), which is
67 | in the lexical '$local' in CODE(0x820c4b0), which was seen before.
68 +- referenced by REF(0x820c204), which is
69 in the global $Test::hash2.
70 87
71It is a bit convoluted to read, but basically it says that the value 88It is a bit convoluted to read, but basically it says that the value
72stored in C<$var> can be found: 89stored in C<$var> is referenced by:
73 90
74=over 4 91=over 4
75 92
76=item - in some variable C<$x> whose origin is not known (I frankly have no 93=item - the lexical C<$closure_var> (0x8abcc8), which is inside an instantiated
77idea why, hints accepted). 94closure, which in turn is used quite a bit.
78 95
79=item - in the hash element with key C<ukukey> in the hash stored in C<%Test::hash>. 96=item - the package-level lexical C<$global_my>.
80 97
81=item - in the global variable named C<$Test::var>. 98=item - the global package variable named C<$Test::var>.
82 99
83=item - in the hash element C<ukukey2>, in the hash in the my variable 100=item - the hash element C<ukukey2>, in the hash in the my variable
84C<$local> in the sub C<Test::testsub> and also in the hash referenced by 101C<$testsub_local> in the sub C<Test::testsub> and also in the hash
102C<$referenced by Test::hash2>.
103
104=item - the hash element with key C<ukukey> in the hash stored in
85C<$Test::hash2>. 105C<%Test::hash>.
106
107=item - some anonymous mortalised reference on the stack (which is caused
108by calling C<track> with the expression C<\$var>, which creates the
109reference).
86 110
87=back 111=back
112
113And all these account for six reference counts.
114
88 115
89=head1 EXPORTS 116=head1 EXPORTS
90 117
91None. 118None.
92 119
103This is the function you most often use. 130This is the function you most often use.
104 131
105=cut 132=cut
106 133
107sub find($); 134sub find($);
135
136sub _f($) {
137 "$_[0] [refcount " . (_refcnt $_[0]) . "]"
138}
108 139
109sub track { 140sub track {
110 my ($ref, $depth) = @_; 141 my ($ref, $depth) = @_;
111 @_ = (); 142 @_ = ();
112 143
120 151
121 if ($depth) { 152 if ($depth) {
122 my (@about) = find $$refref; 153 my (@about) = find $$refref;
123 if (@about) { 154 if (@about) {
124 for my $about (@about) { 155 for my $about (@about) {
156 $about->[0] =~ s/([^\x20-\x7e])/sprintf "\\{%02x}", ord $1/ge;
125 $buf .= "$indent" . (@about > 1 ? "+- " : " ") . $about->[0]; 157 $buf .= "$indent" . (@about > 1 ? "+- " : "") . $about->[0];
126 if (@$about > 1) { 158 if (@$about > 1) {
127 if ($seen{ref2ptr $about->[1]}++) { 159 if ($seen{ref2ptr $about->[1]}++) {
128 $buf .= " $about->[1], which was seen before.\n"; 160 $buf .= " " . (_f $about->[1]) . ", which was seen before.\n";
129 } else { 161 } else {
130 $buf .= " $about->[1], which is\n"; 162 $buf .= " " . (_f $about->[1]) . ", which is\n";
131 $track->(\$about->[1], $depth - 1, $about == $about[-1] ? "$indent " : "$indent| "); 163 $track->(\$about->[1], $depth - 1, $about == $about[-1] ? "$indent " : "$indent| ");
132 } 164 }
133 } else { 165 } else {
134 $buf .= ".\n"; 166 $buf .= ".\n";
135 } 167 }
140 } else { 172 } else {
141 $buf .= "$indent not referenced within the search depth.\n"; 173 $buf .= "$indent not referenced within the search depth.\n";
142 } 174 }
143 }; 175 };
144 176
145 $buf .= "$ref is\n"; 177 $buf .= (_f $ref) . " is\n";
178
146 $track->(\$ref, $depth || $ENV{PERL_DEVEL_FINDREF_DEPTH} || 10, ""); 179 $track->(\$ref, $depth || $ENV{PERL_DEVEL_FINDREF_DEPTH} || 10, "");
147 $buf 180 $buf
148} 181}
149 182
150=item @references = Devel::FindRef::find $ref 183=item @references = Devel::FindRef::find $ref
160=cut 193=cut
161 194
162sub find($) { 195sub find($) {
163 my ($about, $excl) = &find_; 196 my ($about, $excl) = &find_;
164 my %excl = map +($_ => undef), @$excl; 197 my %excl = map +($_ => undef), @$excl;
165 grep !exists $excl{ref2ptr $_->[1]}, @$about 198 grep !($#$_ && exists $excl{ref2ptr $_->[1]}), @$about
166} 199}
167 200
168=item $ref = Devel::FindRef::ptr2ref $integer 201=item $ref = Devel::FindRef::ptr2ref $integer
169 202
170Sometimes you know (from debugging output) the address of a perl scalar 203Sometimes you know (from debugging output) the address of a perl scalar

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines