Perl的caller()函数返回错误的行号

Ste*_*ieD 6 perl

我在Perl 5.10.1上运行了以下脚本:

#!/usr/bin/perl
use strict;
use warnings;

foreach( my $x =0 ; $x < 1; $x++) {   # Line 5
  print_line();                       # Line 6
} 

sub print_line {
  print "Function call from line: " . [caller(0)]->[2] . "\n";
}
Run Code Online (Sandbox Code Playgroud)

尽管调用了来自第6行的子例程,但脚本输出了C-style for语句的起始行号:

Function call from line: 5
Run Code Online (Sandbox Code Playgroud)

真正奇怪的是,如果我将一个随机语句放入C-style for循环中的一个空行,caller返回正确的行号:

#!/usr/bin/perl
use strict;
use warnings;

foreach( my $x =0 ; $x < 1; $x++) {
  my $x = 3;
  print_line();  # Line 7
}

sub print_line {
  print "Function call from line: " . [caller(0)]->[2] . "\n";
}
Run Code Online (Sandbox Code Playgroud)

上面的脚本正确输出:

Function call from line: 7
Run Code Online (Sandbox Code Playgroud)

这是某种错误还是我可以做些什么caller来准确报告行号?

hob*_*bbs 7

我认为可能是一个错误,因为如果你替换,不会发生同样的行为

foreach (my $x = 0 ; $x < 1 ; $x++) {
Run Code Online (Sandbox Code Playgroud)

foreach my $x (0 .. 0) {
Run Code Online (Sandbox Code Playgroud)

我不确切知道发生了什么,但是通过比较两个不同版本的选项,我认为nextstateop正在得到不正确的优化.我的版本有

<;> nextstate(main 4 lineno.pl:11) v:*,&,x*,x&,x$,$ ->8
Run Code Online (Sandbox Code Playgroud)

作为左兄弟entersub调用运算print_line,而你拥有

<0> ex-nextstate v ->8
Run Code Online (Sandbox Code Playgroud)

已经从执行流程中取出.

把它写成一个perlbug并不会有什么坏处.


ike*_*ami 5

$ perl -MO=Concise a.pl
j  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 6 a.pl:5) v:*,&,{,x*,x&,x$,$ ->3
5     <2> sassign vKS/2 ->6
3        <$> const[IV 0] s ->4
4        <0> padsv[$x:3,5] sRM*/LVINTRO ->5
6     <0> unstack v* ->7
i     <2> leaveloop vK/2 ->j
7        <{> enterloop(next->b last->i redo->8) v ->e
-        <1> null vK/1 ->i
h           <|> and(other->8) vK/1 ->i
g              <2> lt sK/2 ->h
e                 <0> padsv[$x:3,5] s ->f
f                 <$> const[IV 1] s ->g
-              <@> lineseq vK ->-
-                 <@> scope vK ->b                       <---
-                    <0> ex-nextstate v ->8              <---
a                    <1> entersub[t5] vKS/TARG,2 ->b
-                       <1> ex-list K ->a
8                          <0> pushmark s ->9
-                          <1> ex-rv2cv sK/2 ->-
9                             <#> gv[*print_line] s/EARLYCV ->a
c                 <1> preinc[t2] vK/1 ->d
b                    <0> padsv[$x:3,5] sRM ->c
d                 <0> unstack v ->e
a.pl syntax OK
Run Code Online (Sandbox Code Playgroud)

有一些优化正在进行中.将scope被认为是不必要的,最优化了.(注意" -"表示从未到达过.)

但与此同时,删除了nextstateop,这就是设置警告和行的行号caller.

因此,这是一个由不正确的优化导致的错误.