Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Debugger and lexicals

by lzipin (Acolyte)
on Aug 06, 2011 at 22:36 UTC ( [id://919000]=perlquestion: print w/replies, xml ) Need Help??

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

I'm seeking enlightenment! This is about the Perl debugger and lexicals ('my' variables). Here's a script:

#! /usr/bin/perl -ws use mytest2; print mt2(55), "\n";

And here's the module it use's:

#! /usr/bin/perl -w package mytest2; require Exporter; our @ISA = qw( Exporter ); our @EXPORT = qw( mt2 ); my $a = 23; sub mt2 { my $b = $_[0] * 2; # return $a + $b; } 1;

My problem is this: With the return line in mt2() commented as shown, I run the top script via 'perl -d' and single-step to the first line of mt2() (that line hasn't executed yet). The debug command 'x $a' returns 'undef' - the debugger can't 'see' $a, even though it is declared earlier in the module file.

When the indicated line is uncommented, this isn't the case anymore -- the debugger reports the proper value of $a before the first line of mt2() is executed, even before it gets referenced or used (in the second line).

I can add code to reference the lexical vars in a module's subroutine that I can set a breakpoint in. But can I not access those lexicals directly? - anyway? - via the debugger?

Replies are listed 'Best First'.
Re: Debugger and lexicals
by dave_the_m (Monsignor) on Aug 07, 2011 at 07:09 UTC
    The variable has been freed by the time you try to examine it. Each executed file has an implied {} scope round it, and when the file is 'use'd, it is compiled, executed, $a is created and freed, and then the use returns. You can confirm this if you like, by assigning an object to $a with a destructor that prints out an "I'm freed" diag message.

    By referring to $a within mt2, you turn mt2 into a closure, which extends the life of $a2 (to that of the life of mt2). Again, using an object you an see that this is the case.

    Dave.

Re: Debugger and lexicals
by jethro (Monsignor) on Aug 06, 2011 at 23:32 UTC

    Maybe $a gets optimized away, because it is not used anywhere in the sub

Re: Debugger and lexicals
by Khen1950fx (Canon) on Aug 07, 2011 at 09:28 UTC
    What's happening is that the control for the debugger must be outside the debugger's internals. Control is in a 'sandbox'. In order to keep control, you can directly access package variables. However, the lexical variables, the 'my'-ed variables, cannot be directly accessed outside of perl.

    The debugger ultimately will settle on 'my', but only after the routine has executed. Then you can play with and view the lexical variables all you want.

      No; there is no control or sandbox and the debugger, being written in perl, is part of perl.

      Lexical variables are only accessible from within a lexical scope, because they only exist within a lexical scope.

      You can use padwalker (y) to list lexicals in a higher scope.

      I think jethro is right, and my $a probably gets optimized away

        Some of what you say I can agree with. But "they only exist within a lexical scope"---and why's that? It's because lexical variables cannot access the symbol table. That's why I mentioned that there's a control "sandboxed" way from the debugger. Package variables can be accessed via the symbol table.

        As for my $a getting optimized away, I disagree with that because I just don't see how it can be optimized away when it's uninitialized in the subroutine. Here's a little test that I ran:

        #!/usr/bin/perl use strict; use warnings; print mt2(55), "\n"; my $a = 23; sub mt2 { my $b = $_[0] * 2; return $a + $b; }
        Here's the corrected script:
        #!/usr/bin/perl use strict; use warnings; print mt2(55), "\n"; sub mt2 { my $a = 23; my $b = $_[0] * 2; return $a + $b; }
        This one works in the debugger. Thanks for the input.
Re: Debugger and lexicals
by Anonymous Monk on Aug 07, 2011 at 07:05 UTC

    Running your program under 5.12.2 and 5.14.1 causes some kind of infinite loop in the debugger, so the code doesn't run at all :)

    Under 5.6.1, I can access $a and $b no problem

    $ C:\MinGW\msys\1.0\bin\perl.exe -d mytest2.pl Default die handler restored. Loading DB routines from perl5db.pl version 1.07 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(mytest2.pl:3): print mt2(55), "\n"; DB<1> s mytest2::mt2(mytest2.pm:11): my $b = $_[0] * 2; DB<1> x $a 0 23 DB<2> x $b 0 undef DB<3> n mytest2::mt2(mytest2.pm:12): return $a + $b; DB<3> x $a 0 23 DB<4> x $b 0 110 DB<5> n 133 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<5> q

    For future references, your demos should always add up to 42 :p

Re: Debugger and lexicals
by lzipin (Acolyte) on Aug 08, 2011 at 03:46 UTC

    Monks, I appreciate the variety of comments. In response, I made some variants to my test code.

    In mytest2.pm, add a second subroutine below the first:

    sub mt3 { return $a + 19; }

    There's no call to mt3() in the top-level script. Nonetheless, the interpreter doesn't know that (I don't think), and shouldn't make $a disappear. But adding the additional sub definition doesn't change the outcome: the debugger still doesn't see $a inside mt2() (with the commented line in place).

    Change #2: our $a; instead of my $a; . Now, the debugger sees $a on the first line of mt2() , whether or not there's a mt3() defined.

    Surely it's a matter of $a being a lexical. But the debugger knows about 'global' lexicals if they're used in a function in which the debugger has stopped, and doesn't if they're not used there -- even when the lexicals are available to the whole module (well, from definition to EOF).

    I don't know enough about the debugger to know if this is by design, or I haven't set a switch or option, or other operator error. Is this where PadWalker comes in?

    -- Lee

      This has nothing to do with the debugger and everything to do with closures. All the debugger does is do the equivalent of executing an eval at the point of interest in the code. Consider the following:
      { my $a = 1; sub f1 { $a; print "f1: a=", eval('$a'), "\n"; } sub f2 { print "f2: a=", eval('$a'), "\n"; } } f1(); f2();
      when run, this outputs:
      f1: a=1 f2: a=
      (The block is there to mimic the implied block that's wrapped around a use'd file). Here, f1 creates a closure, which means it captures the initial (and in this case, only) instance of $a; i.e. a reference to $a is stored in f1's pad. During execution, when the block end is reached, $a goes out of scope for the main sub, and the reference to it from the main pad is removed. When the evals are run, the eval in f1 sees $a since that sub has captured it; whereas the f2 eval can't see it, as it wasn't captured by f2, and no longer exists in the parent.

      Dave.

Re: Debugger and lexicals
by lzipin (Acolyte) on Aug 18, 2011 at 00:48 UTC

    Monks, my thanks to 'dave the m' and the rest of you that contributed to this thread. My eyes have been opened, and now I see ... that even if there's a my var declared in a block prior to a sub definition, obvious to me plain as day, and surely the sub can use it -- yet, after the compile phase, the my var may be gone. I see it (lexically!) in the code, but it's gone. Sure, if the sub uses it, it's squirreled away a ref to it in its pad. And the debugger knows about pads and such.

    It wasn't clear to me that lexicals are for the compiler, and may not exist after the compiler phase.

    -- Lee

Log In?
Username:
Password:

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

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

    No recent polls found