Caller () Perl function returns invalid line number

I have the following script running on 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"; } 

Despite calling the routine starting at line 6, the script prints the line number of the beginning of the C-style statement for:

 Function call from line: 5 

Which is really strange, if I throw a random statement into one of the empty line of the C loop, caller returns the correct line number:

 #!/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"; } 

The above script will correctly output:

 Function call from line: 7 

Is this some kind of error, or is there something I can do to get a caller to accurately report the line number?

+5
source share
3 answers
 $ 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 

There is some optimization going on. scope was considered unnecessary and optimized. (Note the " - ", which means that he never got it.)

But at the same time, it removed the nextstate op statement, which sets the line number for warnings and for caller .

So this is an error caused by improper optimization.

+4
source

I think this is potentially a mistake because the same behavior does not occur if you replace

 foreach (my $x = 0 ; $x < 1 ; $x++) { 

from

 foreach my $x (0 .. 0) { 

I do not understand what is happening, but comparing the preferences of two different versions, I think that a nextstate op gets the wrong optimization. My version has

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

like the left brother of entersub op, which calls print_line , while you have

 <0> ex-nextstate v ->8 

which was taken out of the execution thread.

It wouldn't hurt to write this as perlbug .

+7
source

I suspect that this may be before the statement separators (semicolons). As you may have noticed - with the code you use, the line number specified by caller is the same as the foreach .

So, I think what happens because there are no semicolons.

If you need to execute a multi-line subtitle, caller will report the first line:

 print "first call:", __LINE__, "\n"; print "Start of statement\n", "a bit more on line ", __LINE__, "\n", print_line( 1, 2, 3, 5, ); 

You get the line number of the start of the call, not the end. Therefore, I think that what you get - the statement begins with a comma separator - is the foreach line in the first example.

So, as a workaround - I could suggest using __LINE__ . Although I also probably suggest that you don’t worry too much about it, because it will still point you to the right place in the code.

You get something similar if you use croak , for the same reason.

+2
source

Source: https://habr.com/ru/post/1213883/


All Articles