Skip Menu |

This queue is for tickets about the Devel-FindRef CPAN distribution.

Report information
The Basics
Id: 35363
Status: resolved
Priority: 0/
Queue: Devel-FindRef

People
Owner: Nobody in particular
Requestors: chris [...] heathens.co.nz
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.1
Fixed in: (no value)



Subject: [PATCH] Doesn't find all code refs
I found 3 cases where it doesn't find all code refs. 1. Variables referenced in closures (anonymous code refs) 2. Last variable used in a code ref 3. Code refs that are parents of inner code refs. Test cases for each: Case 1: use Devel::FindRef; my $var = "hi\n"; my $t = sub {$var . "bye\n"}; print Devel::FindRef::track(\$var); Case 2: use Devel::FindRef; my $var = "hi\n"; my $t = sub {$var}; print Devel::FindRef::track(\$var); Case 3: use Devel::FindRef; sub testsub { my $var = "hi\n"; my $t = sub { sub test_inner { "foo" } $var; }; $t->(); print Devel::FindRef::track(\$var); } testsub; Some points to note: * The attached patch fixes all these problems, but could do with more refinement. * You will probably have to modify the POD documentation to remove the "not found anywhere I looked :(" from the example output because now it does find the code refs. * This patch exposes some circular references in Perl's internals. Perhaps looking at the WEAKOUTSIDE CV-flag would help, but for my purposes I preferred to err on the side of too much output than to risk missing a valid reference. I hope this helps.
Subject: Devel-FindRef.patch
diff -ur Devel-FindRef-1.1/FindRef.xs Devel-FindRef-1.1-mod/FindRef.xs --- Devel-FindRef-1.1/FindRef.xs 2007-12-29 15:53:16.000000000 -0500 +++ Devel-FindRef-1.1-mod/FindRef.xs 2008-04-23 22:29:18.000000000 -0400 @@ -118,6 +118,7 @@ case SVt_PVCV: { int depth = CvDEPTH (sv); + if (depth == 0 && CvPADLIST(sv)) depth = 1; if (depth) { @@ -129,13 +130,15 @@ av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */ - for (i = AvFILLp (pad); i--; ) + for (i = AvFILLp (pad)+1; i--; ) if (AvARRAY (pad)[i] == targ) res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i]))); --depth; } } + if ((SV*)CvOUTSIDE(sv) == targ) + res_pair ("the containing scope for"); } break;
From: chris [...] heathens.co.nz
Here is an updated patch. It supports the WEAKOUTSIDE flag now, and it works with constant functions (it used to segfault). Here is a test case for constant functions: use Devel::FindRef; use constant testconst => {}; my $var = "hi\n"; testconst()->{'testkey'} = \$var; print Devel::FindRef::track(\$var);
--- Devel-FindRef-1.1/FindRef.xs 2007-12-29 15:53:16.000000000 -0500 +++ Devel-FindRef-1.1-mod/FindRef.xs 2008-04-26 00:28:11.000000000 -0400 @@ -118,6 +118,8 @@ case SVt_PVCV: { int depth = CvDEPTH (sv); + /* Anonymous subs have a padlist but zero depth */ + if (depth == 0 && CvPADLIST(sv)) depth = 1; if (depth) { @@ -129,13 +131,22 @@ av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */ - for (i = AvFILLp (pad); i--; ) + for (i = AvFILLp (pad)+1; i--; ) if (AvARRAY (pad)[i] == targ) - res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i]))); + { + /* Values from constant functions are stored in the pad without any name */ + SV *name_sv = AvARRAY (AvARRAY (padlist)[0])[i]; + char *name = name_sv && SvPOK (name_sv) ? SvPVX (name_sv) : ""; + res_pair (form ("in the lexical '%s' in", name)); + } --depth; } } + if (CvCONST(sv) && (SV*)CvXSUBANY(sv).any_ptr == targ) + res_pair ("the constant value of"); + if (!CvWEAKOUTSIDE(sv) && (SV*)CvOUTSIDE(sv) == targ) + res_pair ("the containing scope for"); } break;
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #35363] [PATCH] Doesn't find all code refs
Date: Sun, 27 Apr 2008 08:14:32 +0200
To: Chris Heath via RT <bug-Devel-FindRef [...] rt.cpan.org>
From: Marc Lehmann <schmorp [...] schmorp.de>
[could you send further correspondance directly to me? I find rt.cpan.org close to unusable but there is no way to switch it off]. On Sat, Apr 26, 2008 at 10:28:38PM -0400, Chris Heath via RT <bug-Devel-FindRef@rt.cpan.org> wrote: Show quoted text
> Here is an updated patch. It supports the WEAKOUTSIDE flag now, and > it works with constant functions (it used to segfault).
Hi! Thanks a lot for your patches (I did release 1.2 earlier, but didn't have the time to talk to you). I applied this patch (and will release it as 1.3), but I cannot see the difference (I changed the patch slightly, but that shouldn't affect the outcome). (You can find the CVS at http://software.schmorp.de/pkg/Devel-FindRef, btw) Are you using 5.8? Maybe this changed with 5.10? I use 5.10: SCALAR(0x7bd330) is in the lexical '$var' in CODE(0x79f4e8), which is not found anywhere I looked :( referenced by REF(0x79f2f0), which is not found anywhere I looked :( referenced by REF(0x79f140), which is in the member 'testkey' of HASH(0x81e6a8), which is referenced by REF(0x7c49c0), which is referenced by REF(0x7c3e38), which is in the member 'testconst' of HASH(0x79f158), which is in the global %main::main::. Worse, with debians perl (threaded + 5.8) it segfaults, reason: #0 0x00002b0454c32bb7 in XS_Devel__FindRef_find_ (my_perl=<value optimized out>, cv=<value optimized out>) at FindRef.xs:144 144 if (name_sv && SvPOK (name_sv)) (gdb) p name_sv $1 = (SV *) 0x303030303030303 yay :) Thanks a lot for your patches so far, and especially for the separate testcases! -- The choice of a Deliantra, the free code+content MORPG -----==- _GNU_ http://www.deliantra.net ----==-- _ generation ---==---(_)__ __ ____ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / pcg@goof.com -=====/_/_//_/\_,_/ /_/\_\
Thanks, applied, see private correspondence.