Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I watch for changes to an expression in the Perl debugger?

With the Perl debugger, I know I can set breakpoints at certain lines of code with the b command. Can I get the debugger to stop as soon as the contents of a variable has changed?

like image 424
Flimm Avatar asked Dec 07 '22 03:12

Flimm


1 Answers

You can create watch points using the w command in the Perl debugger.

Crash course on the w debugger command:

Create a watch-expression by typing w and then an expression that will monitored for changes:

DB<1> w $variablename

Enter c to continue until the watched expression changes. Once you do, you will get output similar to this:

DB<2> c
Watchpoint 0:   $variablename changed:
    old value:  ''
    new value:  'hi'
main::(ex.pl:6):    $variablename = "";    

Note that the debugger stops at the statement after the changed has happened, so the line displayed might not be relevant at all.

Also note that the expression is stringified. So for example, changing a variable to undef will give you this output:

  DB<2> c
Watchpoint 0:   $variablename changed:
    old value:  'hi'
    new value:  ''
main::(ex.pl:7):    $variablename = undef;

If the variable is subsequently changed to an empty string, the debugger will not stop, as a stringified empty string and a stringified undef is considered equal.

If the watch expression is a list, the debugger will compare the stringified elements of the list:

  DB<1> w $variablename, "second"

  DB<2> c
Watchpoint 0:   $variablename, "second" changed:
    old value:  'one', 'second'
    new value:  'two', 'second'
main::(hi.pl:6):    $variablename = "three";

You can use array variables or hash variables as watch-expressions, and they will be treated as any other list.

To delete a watch-expression, use the W command, and to view a list of active watch-expressions, use the L command.

Tip: Use temporary global variables

Since the watch-expression is re-evaluated with every statement, you can't expect a watch-expression that uses a lexical variable to work out of scope. A quick tip is to create a global reference to the lexical, and track that instead:

DB<1> $main::my_debug_variable = $hashref_lexical_variable

DB<2> w $main::my_debug_variable->{key_im_watching}

Tip: Use Data::Dumper

Use Data::Dumper to watch the contents of a non-scalar:

DB<1> w Data::Dumper->Dump([$hashref])

This is preferable to a simple w $hashref, because it will stop when the values of the hash change, rather than simply the address the reference is pointing (since a hashref stringifies to something like HASH(0x2a07a90)).

like image 63
Flimm Avatar answered Jan 12 '23 00:01

Flimm