Re: How can I print variable contents from the debugger non-interactively?
by Marshall (Canon) on Jul 15, 2017 at 04:25 UTC
|
I am trying to debug a perl script without modifying it.
The single most powerful debug tool in Perl is "print" and Data::Dumper and its kinfolk like Data::Dump. Why is not modifying the program a requirement? Why not just add some print statements and be done with it?
During debug, I add print statements all the time with a comment tag field to make them easy to delete later (my program editor makes that easy). The "change code, recompile, execute code" cycle is so fast (if you have a good development environment) in Perl that modifying the code to debug it is very sensible.
Sometimes I will leave some debug statements in the code. These are things that I am likely to need later if there is some significant modification to the code.
use constant DEBUG =>1;
...
if (DEBUG){...code}
In Perl if you set DEBUG =>0, there is no speed penalty for that if statement because Perl knows due to the constant value that the code will never be executed and it is not even compiled.
Maybe you can find all kinds of tricky debug statements to get the debugger to do what you want right now. However, you will not know that stuff years from now when you are debugging some modification. For the most part, I recommend using "print" for transient debug issues. For some code where modifications are likely to require examining some data structure, I put in in if(DEBUG). | [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] [d/l] |
|
|
Marshall thank you for your reply, additional description for why one might want to debug the script without modifying it has been provided in the orginal question.
Maybe you can find all kinds of tricky debug statements to get the debugger to do what you want right now.
However, you will not know that stuff years from now when you are debugging some modification.
I don't agree with this sentiment, I think learning to use the debugger and understanding how to use it to print
and maybe even modify runtime behavior of the script without modification is a skill that could be useful years from now
(i have a good memory and places to document the perl wisdom gleaned from this question/responses).
Using print/debug statements is easy and effective, but I'm looking to further my understanding of basic perl tools and add to perl repertoire.
| [reply] |
|
|
Hi Dave!
I was thinking of interactive debug commands.
I believe that you will find in Perl,
that the debugger is seldom used because its not required. I have to use a debugger (mandatory) when I write assembly code, I very seldom use a debugger for C code and almost never use a debugger for Perl code - for me, the Perl debugger is a once in a decade event. I have never required the Perl debugger to solve a code problem.
I congratulate you on your curiosity and motivation to learn more about Perl!
Perl is an amazingly introspective language. A Perl user function can find out things that are just not possible for a C program.
Some useful stuff for debugging the caller stack is the Perl Caller() function.
Some "standard" functions:
$me = whoami();
$him = whowasi();
sub whoami { (caller(1))[3] }
sub whowasi { (caller(2))[3] }
I recommend study of the caller() function for your "debug repertoire".
| [reply] [d/l] |
Re: How can I print variable contents from the debugger non-interactively?
by LanX (Saint) on Jul 15, 2017 at 01:02 UTC
|
It's a bit vague, under which condition do you want the variables to be printed?
Here some approaches
- Set a watch expression which doesn't stop
- Change &DB::DB
- change &DB::sub
See perldebguts#Writing-Your-Own-Debugger for inspiration.
For instance PERL5DB="sub DB::DB { print $var }" perl -d your-script
should continously print $var for each statement. (Untested)
HTH
| [reply] [d/l] |
|
|
Thank you very much LanX for the reply.
Using PERL5DB="sub DB::DB { print $var }" perl -d your-script is a really great idea. I was not aware of the DB::DB sub.
I tried defining this and running it with something like:
PERL5DB="sub DB::DB { print \"VAR: \$var\n\" if(defined \$var); }" perl -d your-script
However, it seems that this affects the way the std debugger works as I do not get the output from the debugger listing all the lines that are executed as before. It seems to not be called recursively all the way through the program without the std. debugger working. Looks like it only gets called top level and internal statements are not getting the DB::DB injected before execution.
I saw your responses giving commands to the debugger ie. watch and action statements etc. Is there a way to provide this to the debugger via the $ENV{PERLDB_OPTS} variable?
Thanks again.
--dave
| [reply] |
|
|
> , it seems that this affects the way the std debugger works
yes, it's still unclear for me if you want to step thru or run an automatic trace.
> Is there a way to provide this to the debugger via the $ENV{PERLDB_OPTS} variable?
Yes.
edit
At least in .perldb with afterinit
sub afterinit { push @DB::typeahead, "b 4", "b 6"; }
See perldebug#Debugger-Customization
| [reply] [d/l] |
|
|
|
|
|
|
|
Re: How can I print variable contents from the debugger non-interactively?
by zentara (Cardinal) on Jul 15, 2017 at 11:42 UTC
|
Hi, if you would like a perl GUI for debugging, wherein you can set
beakpoints, watched-variables, etc, try Devel-ptkdb which is a PerlTk
frontend to debug. A TCL frontend is availble too.
You can save your settings for multiple runs.
There are numerous tutorials available if you google for "perl debugging ptkdb".
It's actually very convenient to use.
| [reply] |
|
|
There's also Devel::hdb which runs a web server to which you can connect from your browser and set breakpoints and watch variables there.
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] |
|
|
I like the Komodo IDE integration, not sure if it's included in the free Ko modo Edit version.
| [reply] |
Re: How can I print variable contents from the debugger non-interactively? ( a = line action ; w = watch changes everywhere)
by LanX (Saint) on Jul 15, 2017 at 10:42 UTC
|
> to print all the variable contents when executing line XXX
some hands on examples
a action (per line) and w watchpoint (each time) take Perl code to be evaluated.
you can do pretty nifty things with that already
sample code
use strict;
use warnings;
$|=1; # disable buffering
my $a;
our $y;
for (0..10) {
print;
$a++;
$y++;
}
a = action cmd on line
DB<71> h a
a [line] command
Set an action to be done before the line is executed;
line defaults to the current execution line.
Sequence is: check for breakpoint/watchpoint, print line
if necessary, do action, prompt user if necessary,
execute line.
a Does nothing
a doesn't break unless you set $DB::single explicitly to 1
w = watch-expression
DB<79> h w
w expr Add a global watch-expression.
w Does nothing
w stops if the returned value has changed
w $a would stop each time $a is changing
this only stops if $a is inside the intervall
this only stops for the first print and the first non print (print returns 1)
| [reply] [d/l] [select] |
|
|
DB<119> b 11 print "\n<$y>\n" if $y==3;0
DB<120> L
d:/Users/RolfLangsdorf/AppData/Roaming/pm/tst_debuger.pl:
11: $a++;
break if (print "\n<$y>\n" if $y==3;0)
DB<120> c
0123
<3>
45678910 DB<120>
| [reply] [d/l] |
Re: How can I print variable contents from the debugger non-interactively? ( { = auto cmd ; X V y = dump by regex)
by LanX (Saint) on Jul 15, 2017 at 13:06 UTC
|
DB<162> h X
X [vars] Same as "V currentpackage [vars]".
DB<163> h V
V [pkg [vars]] List some (default all) variables in package (defaul
+t current).
Use ~pattern and !pattern for positive and negative regexps.
DB<164> h y
y [n [Vars]] List lexicals in higher scope <n>. Vars same as V.
With "{" you can tell the debugger to automatically execute these (and other debugger) commands with each prompt, like when single stepping or when running into a breakpoint.
DB<1> h {
{ db_command Define debugger command to run before each prompt.
{ ? List debugger commands to run before each prompt.
{{ db_command Add to the list of debugger commands to run before ea
+ch prompt.
{ * Delete the list of debugger commands to run before eac
+h prompt.
The following example
- sets a conditional breakpoint at line 11
- dumps all variables named y before each prompt
c = continue runs into the breakpoint
s = single step shows the dumping
DB<239> b 11 $a==3
DB<240> L
d:/Users/RolfLangsdorf/AppData/Roaming/pm/tst_debuger.pl:
11: $a++;
break if ($a==3)
DB<240> { X y
DB<241> {
pre-debugger commands:
{ -- X y
DB<241> c
0123auto(-1) DB<241> X y
$y = 3
DB<242> s
auto(-1) DB<242> X y
$y = 3
DB<243> s
auto(-1) DB<243> X y
$y = 4
DB<244> c
45678910auto(-1) DB<244> X y
DB<245>
| [reply] [d/l] [select] |
Re: How can I print variable contents from the debugger non-interactively?
by Laurent_R (Canon) on Jul 15, 2017 at 08:32 UTC
|
Hi davehorner,
It seems to me that the answers you've received so far may probably be more complicated than what you actually wanted to know.
To print the content of a scalar variable $var, simply issue the following commands at the debugger prompt:
p $var
Sometimes it is better to put some special characters around the variable in order to see possible invisible characters:
p "<$var>"
To see the content of a non scalar variable such as an array or a hash, use the x command:
x @array
or use a reference to the variable for a clearer output:
x \%hash;
And remember you can always issue the h command at the debugger prompt to get some help:
DB<1> h
List/search source lines: Control script execution:
l [ln|sub] List source code T Stack trace
- or . List previous/current line s [expr] Single step [in
+expr]
v [line] View around line n [expr] Next, steps over
+ subs
f filename View source in file <CR/Enter> Repeat last n or
+ s
/pattern/ ?patt? Search forw/backw r Return from subr
+outine
M Show module versions c [ln|sub] Continue until p
+osition
Debugger controls: L List break/watch
+/actions
o [...] Set debugger options t [expr] Toggle trace [tr
+ace expr]
<[<]|{[{]|>[>] [cmd] Do pre/post-prompt b [ln|event|sub] [cnd] Set b
+reakpoint
! [N|pat] Redo a previous command B ln|* Delete a/all bre
+akpoints
H [-num] Display last num commands a [ln] cmd Do cmd before li
+ne
= [a val] Define/list an alias A ln|* Delete a/all act
+ions
h [db_cmd] Get help on command w expr Add a watch expr
+ession
h h Complete help page W expr|* Delete a/all wat
+ch exprs
|[|]db_cmd Send output to pager ![!] syscmd Run cmd in a sub
+process
q or ^D Quit R Attempt a restar
+t
Data Examination: expr Execute perl code, also see: s,n,t expr
x|m expr Evals expr in list context, dumps the result or lists
+ methods.
p expr Print expression (uses script's current package).
S [[!]pat] List subroutine names [not] matching pattern
V [Pk [Vars]] List Variables in Package. Vars can be ~pattern or !
+pattern.
X [Vars] Same as "V current_package [Vars]". i class inherita
+nce tree.
y [n [Vars]] List lexicals in higher scope <n>. Vars same as V.
e Display thread id E Display all thread ids.
For more help, type h cmd_letter, or run man perldebug for all docs.
| [reply] [d/l] [select] |
|
|
Well he said "non-interactively" , but yeah he might mean it differently.
| [reply] |
|
|
| [reply] |
|
|