Eugen Konkov Eugen Konkov - 5 months ago 8
Perl Question

Why does this workaround for magic Perl internal variable work?

t2.pl



1;
2;
3;


t.pl



package DB;

sub DB {
print "HERE";

our(undef, $f, undef) = caller;

# This does not work
# my $ref = \%{ "main::_<$f" };
# $ref->{ 3 } = {};

# This does not work
# *x = $main::{ "_<$f" };
# $x{ 3 } = {};

*dbline = $main::{ "_<$f" };
$dbline{ 3 } = {};

$DB::single = 0;
}

1;




PERL5DB="BEGIN{ require 't.pl' }" perl -d t2.pl


When you run this code you get
HEREHERE
, but the magic Perl variable has no effect when you do not alias it using
*dbline
.

So when you change first two examples to look like:

*dbline = $main::{ "_<$f" }; # <<<<<<<<< With this it works!!!!
*x = $main::{ "_<$f" };
$x{ 3 } = { };


the breakpoint starts to work. (This is applied to Perl 5.14.4)

Why does it work in such way?

DOC

Answer

This has been reported before:

perldebguts says:

  • Each hash %{"_<$filename"} contains breakpoints and actions keyed by line number. Individual entries (as opposed to the whole hash) are settable.

This implies that breakpoints set on %{"_<..."} apply to the named file. That is not actually true, as every %{"_<..."} hash sets breakpoints on lines in @DB::dbline, regardless of which file it refers to. The assumption is that debuggers will alias *DB::dbline to *{"_<..."} before setting any breakpoints.

Hence, all %{"_<..."} hashes are the same.

Is this a case where the documentation should be expanded to match the implementation? Or should we change the implementation to make each %{"_<..."} hash work on its corresponding @{"_<..."} array? The latter seems more useful to me.

In 5.20.0, the behavior was changed so that you don't have to alias @DB::dbline:

$ PERL5DB='
  sub DB::DB {
      ($p,$f,$l) = caller;
      print "$f:$l\n";
      ${"::_<$f"}{3} = 1; # no need for alias
      $DB::single = 0
  }
' perl -d foo
foo:1
foo:3
Comments