为什么 Perl 在这个警告消息中提供了一个误导性的行号? [英] Why does Perl provide a misleading line number in this warning message?
问题描述
我已经隔离了一个案例,其中 Perl 在警告消息中提供了一个非常具有误导性的行号.我在 Strawberry Perl 5.16.3 中测试了以下内容.
I have isolated a case where Perl provides a very misleading line number in a warning message. I tested the below in Strawberry Perl 5.16.3.
use strict;
use warnings;
my $choice = 0;
while ($choice == 0){
#This is not numeric
$choice = '5,6,7';
if ($choice eq '-4'){
print "This isn't going to happen\n";
}
}
当您运行此程序时,您将收到警告消息 Argument "5,6,7" is not numeric in numeric eq (==) at example.pl line 11
.但是第 11 行对应于 if ($choice eq '-4'){
行,它不可能导致此警告消息,因为它不包含数字比较.
When you run this, you will get the warning message Argument "5,6,7" isn't numeric in numeric eq (==) at example.pl line 11
. But line 11 corresponds to the line if ($choice eq '-4'){
which cannot possibly cause this warning message because it does not contain a numeric comparison.
看起来实际上发生的是 Perl 前进到下一个比较,while ($choice == 0){
,但是用于警告消息的行计数器不前进.
It seems what's actually happening is that Perl advances to the next comparison, while ($choice == 0){
, but the line counter used for the warning message does not advance.
让这个特殊情况变得更糟的是,由于坏"比较是循环条件,它实际上远离提供的行.在我的(简化前)脚本中,它与提供的行号相距数百行.
What makes this particular case worse is that, since the "bad" comparison is the loop condition, it is actually far away from the provided line. In my (pre-simplification) script, it was hundreds of lines away from the provided line number.
这是一个错误还是只是解析器的一个不幸的限制?
Is this a bug or just an unfortunate limitation of the parser?
推荐答案
存储每个操作符实例的位置会很昂贵.作为妥协,Perl 只跟踪语句的位置.它通过在每个语句的开头添加一个位置设置操作码来实现.if
语句是执行 $choice == 0
之前要启动的最后一条语句,因此报告警告为来自该行.
It would be expensive to store the location of each operator instance. As a compromise, Perl only tracks the location of statements. It does so by adding a location-setting opcode at the start of every statement. The if
statement is the last statement to be started before $choice == 0
is performed, so the warning is reported as coming from that line.
$ perl -MO=Concise,-exec a.pl
1 <0> enter
2 <;> nextstate(main 3 a.pl:4) v:*,&,{,x*,x&,x$,$
3 <$> const[IV 0] s
4 <0> padsv[$choice:3,12] sRM*/LVINTRO
5 <2> sassign vKS/2
6 <;> nextstate(main 4 a.pl:6) v:*,&,{,x*,x&,x$,$ <--- Location set to line 6
7 <{> enterloop(next->k last->p redo->8) v <--- Start of while loop
l <0> padsv[$choice:3,12] s <--- $choice == 0
m <$> const[IV 0] s
n <2> eq sK/2
o <|> and(other->8) vK/1
8 <;> nextstate(main 6 a.pl:9) v:*,&,x*,x&,x$,$
9 <$> const[PV "5,6,7"] s
a <0> padsv[$choice:3,12] sRM*
b <2> sassign vKS/2
c <;> nextstate(main 6 a.pl:11) v:*,&,x*,x&,x$,$ <--- Location set to line 11
d <0> padsv[$choice:3,12] s <--- Start of if statement
e <$> const[PV "-4"] s
f <2> seq sK/2
g <|> and(other->h) vK/1
h <0> pushmark s
i <$> const[PV "This isn't going to happen\n"] s
j <@> print vK
k <0> unstack v
goto l <--- Jump back to loop expr
p <2> leaveloop vKP/2
q <@> leave[1 ref] vKP/REFC
a.pl syntax OK
这是一个已知的限制.我不知道他们为什么不简单地在循环表达式中放置一个 nextstate
操作.
This is a known limitation. I don't know why they don't simply put a nextstate
op in the loop expression.
这篇关于为什么 Perl 在这个警告消息中提供了一个误导性的行号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!