2015-02-21 4 views
5

Ho il seguente script in esecuzione su Perl 5.10.1:chiamante di Perl() funzione che restituisce riga errata numero

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

Nonostante la chiamata alla subroutine proveniente dalla linea 6, lo script emette il numero di riga dell'inizio dello stile di C per la dichiarazione:

Function call from line: 5 

la cosa veramente strana è che se mi passi una dichiarazione a caso in uno dei riga vuota in stile C per ciclo, caller restituisce il numero di riga corretto:

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

Lo script precedente uscite correttamente:

Function call from line: 7 

E 'una specie di bug o c'è qualcosa che posso fare per ottenere caller di riportare con precisione il numero di riga?

+0

Interessante - sì, sembra essere il caso. Sembra che restituisca il numero di linea del "loop". La macro '__LINE__' può aiutare a risolvere i problemi. – Sobrique

risposta

4
$ 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 

C'è qualche ottimizzazione in corso. Lo scope è stato ritenuto non necessario e ottimizzato. (Si noti la "-", che significa che non è mai raggiunto.)

Ma allo stesso tempo, che ha rimosso il nextstate op, che è ciò che definisce il numero di riga per gli avvisi e per caller.

Quindi, si tratta di un errore dovuto a un'ottimizzazione impropria.

2

Sospetto che questo possa essere dovuto ai separatori di istruzioni (punto e virgola). Come potresti aver individuato - con il codice che stai utilizzando, il numero di linea riportato da caller è lo stesso del ciclo foreach.

Quindi I penso quello che sta accadendo, è perché non c'è punto e virgola.

Se si dovesse fare un sub chiamata multi-linea, caller riferirà la prima linea:

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

    2, 

    3, 

    5, 

); 

Si ottiene il numero di riga di inizio della chiamata, non la fine. Quindi penso che sia quello che stai ottenendo - la dichiarazione inizia quando si verifica il separatore dell'istruzione punto e virgola - che è la riga foreach nel primo esempio.

Quindi come soluzione alternativa, potrei suggerire di utilizzare __LINE__. Anche se forse suggerirei anche di non preoccuparmene troppo, perché ti indicherà comunque il posto giusto nel codice.

Si ottiene qualcosa di simile se si utilizza croak, presumibilmente per lo stesso motivo.

7

Penso potenzialmente si tratta di un bug, in quanto lo stesso comportamento non si verifica se si sostituisce

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

con

foreach my $x (0 .. 0) { 

non capisco esattamente cosa sta succedendo, ma confrontando gli optrees delle due diverse versioni, penso che un op nextstate si stia ottimizzando in modo improprio. La mia versione ha

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

come il fratello sinistra del entersub op che chiama print_line, mentre il vostro ha

<0> ex-nextstate v ->8 

che è stato tolto dal flusso di esecuzione.

Non sarebbe male scrivere questo come perlbug.

+0

Buon posto. Interessante. Cosa stai usando per estrarre le ottimizzazioni del codice? – Sobrique

+1

@Sobrique B :: Conciso – hobbs

+0

Anche se non riesco a vederlo scritto, sembra che questo sia un bug corretto. Perl 5 versione 20 non mostra questo comportamento. – Borodin