Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

debugging eval'd code with source (SOLVED)

by sharkey (Scribe)
on Jul 09, 2008 at 05:53 UTC ( [id://696388]=perlquestion: print w/replies, xml ) Need Help??

sharkey has asked for the wisdom of the Perl Monks concerning the following question:

I've been debugging code which has eval'd subs in it. Normally when inside these subs, the debugger just shows something line "(eval 20)" for the current subroutine with no code from the current line.

But once, mysteriously, the debugger actually showed me the code which had been eval'd as I stepped through it. I figured if it can happen once, it can happen again, so I started investigating how it could happen.

perldebguts documents the @{"_<(eval 20)"} variables where the code for eval'd stuff should be stored. The trouble is, most of the time, there is no code there for my evals. I can look in the symbol table and see lots of other (eval ##) entries which do have code in them. For example, like this:

DB<20> p join "\n", map { "$_ $#{$_}" } grep /_<\(/, keys %::
So my question for the perl debug gurus out there is, Why do some eval's get their code stored and others do not? Is there anything I can do to encourage my eval'd code to get stored?

EUREKA!

It is the presence of a named sub, or even a named sub stub, which convinces perl to keep the eval'd code in memory. So for my anonymous subs, I can do this:

my $coderef = eval <<'EOF'; sub forget_me_not; sub { print "do some stuff"; } EOF
The debugger can now show me the code for the anonymous sub, even if I use the same stub name in all of the evals.

Replies are listed 'Best First'.
Re: debugging eval'd code with source
by casiano (Pilgrim) on Jul 09, 2008 at 14:24 UTC
    Each time you have an eval step inside the debugger, it replies with s.t. like:
    main::((eval 8)[evals.pl:15]:1):
    The string (eval 8) is the "file" name of the eval. You can use that name to list the eval.

    The following example with the debugger illustrates the point. I will use this listing:

    pp2@nereida:~/src/perl/testing$ cat -n evals.pl 1 use strict; 2 use warnings; 3 4 my ($a, $b) = (1, 9); 5 6 my $x = eval q { 7 $a = 2; 8 $b = 3; 9 print "$b\n"; 10 $a+$b; 11 }; 12 13 14 15 my $y = eval '$a+$b'; 16 17 print "$y\n";
    See how the evals produce the "virtual filenames":
    pp2@nereida:~/src/perl/testing$ perl -wd evals.pl Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(evals.pl:4): my ($a, $b) = (1, 9); DB<1> c 6 main::(evals.pl:6): my $x = eval q { main::(evals.pl:7): $a = 2; main::(evals.pl:8): $b = 3; main::(evals.pl:9): print "$b\n"; main::(evals.pl:10): $a+$b; DB<2> n main::((eval 6)[evals.pl:6]:2): $a = 2; DB<2> l (eval 6) 1 2==> $a = 2; 3: $b = 3; 4: print "$b\n"; 5: $a+$b; 6 7 ;
    See it?. Now I try to stop at line 15
    DB<3> c 15 Line 15 not breakable.
    I fail because I am in file eval not in the main file:
    DB<4> f evals.pl 1: use strict; 2: use warnings; 3 4: my ($a, $b) = (1, 9); 5 6: my $x = eval q { 7 $a = 2; 8 $b = 3; 9 print "$b\n"; 10 $a+$b; DB<5> c 15 3 main::(evals.pl:15): my $y = eval '$a+$b'; DB<6> n main::((eval 8)[evals.pl:15]:1): $a+$b DB<6> l (eval 8) 1==> $a+$b 2 ; DB<7> c 5 Debugged program terminated. Use q to quit or R to restart, use o inhibit_exit to avoid stopping after program termination, h q, h R or h o to get additional info. DB<7>
      Thanks for your answer. Here's a more concrete example to show the problem.
      $ cat -n tt 1 #!/usr/bin/perl 2 3 my $perl = <<'EOF'; 4 sub { 5 my $x = 123; 6 $x += shift; 7 print "x is $x\n" 8 } 9 EOF 10 11 my $cf = eval $perl; 12 13 $cf->(4); $ perl -d tt Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(tt:3): my $perl = <<'EOF'; main::(tt:4): sub { main::(tt:5): my $x = 123; main::(tt:6): $x += shift; main::(tt:7): print "x is $x\n" DB<8> s main::(tt:11): my $cf = eval $perl; DB<8> s main::((eval 20)[tt:11]:7): ;
      Now we are inside the eval, and we can see the code...
      DB<8> p $#{"_<(eval 20)[tt:11]"} 7 DB<9> l (eval 20) 1 sub { 2: my $x = 123; 3: $x += shift; 4: print "x is $x\n" 5 } 6 7==> ;
      But as soon as we step out of the eval, the code is gone...
      DB<10> s main::(tt:13): $cf->(4); DB<10> p $#{"_<(eval 20)[tt:11]"} -1
      And yet, there are other evals out there, for the code stays around...
      DB<11> p join "\n", map { "$_ $#{$_}" } grep /_<\(/, keys %:: _<(eval 20)[tt:11] -1 _<(eval 22)[/usr/lib/perl5/5.8.8/SelfLoader.pm:38] 6 _<(eval 11)[/usr/lib/perl5/5.8.8/SelfLoader.pm:111] 1 _<(eval 12)[/usr/lib/perl5/5.8.8/SelfLoader.pm:38] 40 _<(eval 5)[/usr/lib/perl5/5.8.8/Term/ReadLine.pm:306] -1 _<(eval 21)[/usr/lib/perl5/5.8.8/SelfLoader.pm:38] 10 _<(eval 23)[/usr/lib/perl5/5.8.8/SelfLoader.pm:38] 20 _<(eval 26)[/usr/lib/perl5/5.8.8/perl5db.pl:628] 4 DB<13> f eval 22 Choosing (eval 22)[/usr/lib/perl5/5.8.8/SelfLoader.pm:38] matching `ev +al 22': 1 package readline; sub F_PreviousHistory { 2: &get_line_from_history($rl_HistoryIndex - shift); 3 } 4 5 6 ;
      I no longer can get to my eval'd code...
      DB<14> f eval 20 Choosing (eval 20)[tt:11] matching `eval 20': DB<15> l
      And neither can the debugger...
      DB<15> s main::CODE(0x97b7d28)((eval 20)[tt:11]:2): 2: DB<15> main::CODE(0x97b7d28)((eval 20)[tt:11]:3): 3: DB<15> main::CODE(0x97b7d28)((eval 20)[tt:11]:4): 4: DB<15> x is 127 Debugged program terminated. Use q to quit or R to restart, use o inhibit_exit to avoid stopping after program termination, h q, h R or h o to get additional info.
      So the question remains, why does my eval'd source code get discarded, while other eval'd source code stays in memory? And what can I do to convince perl to keep my eval'd source code?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://696388]
Approved by bingos
Front-paged by DrHyde
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (6)
As of 2024-04-19 16:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found