2015-07-01 3 views
10

haben ein einfaches Skript p.pl:Wie kann man Devel :: Trace überzeugen, die BEGIN-Block-Anweisungen zu drucken?

use strict; 
use warnings; 
our $x; 
BEGIN { 
    $x = 42; 
} 
print "$x\n"; 

Als ich führen Sie es als:

perl -d:Trace p.pl 

druckt:

>> p.pl:3: our $x; 
>> p.pl:7: print "$x\n"; 
42 

, wie der Block-Anweisungen bekommen gedruckt BEGIN, z.B. die $x = 42;?

Weil meine Absicht nicht klar ist, Hinzufügen der Klärung:

für JEDEN Weise gerichteten Aussagen zu drucken, wenn der Perl-Skript ausgeführt wird (wie Devel Trace :: es tut), sondern einschließlich der Aussagen in dem BEGIN Block.

+2

@toolic warum nicht? Es druckt sicherlich einen "END" -Block. Aber zum Zeitpunkt der Ausführung des 'BEGIN' ist es nicht vollständig geladen. – simbabque

+1

Ja. Also, könnte genauer sein. Wie bekomme ich die BEGIN-Blockanweisungen (wie bei der -d: Trace), aber auf andere Weise? (z. B. mit dem DB :: oder so?) – kobame

Antwort

8

Es ist sehr möglich. Set $DB::single in einem frühen BEGIN Block.

use strict; 
use warnings; 
our $x; 
BEGIN { $DB::single = 1 } 

BEGIN { 
    $x = 42; 
} 
print "$x\n"; 

$DB::single ist ein Debugger-Variable verwendet, um zu bestimmen, ob die Funktion DB::DB wird bei jeder Zeile aufgerufen werden. In der Compilierungsphase ist es normalerweise falsch, aber Sie können es in der Kompilierungsphase in einem BEGIN Block setzen.

Dieser Trick ist auch hilfreich, um einen Haltepunkt in einem BEGIN Block festzulegen, wenn Sie den Kompilierungszeitcode im Standarddebugger debuggen möchten.

+0

Vielen Dank. Eine Frage. Wo ist das dokumentiert? – kobame

+0

https://metacpan.org/pod/perldebug#Debugging-Compile-Time-Statements, für einen – mob

+0

Lustig, wie ich darüber nachgelesen habe, als ich meine Antwort recherchiert habe. Mir ist nicht eingefallen, es zu versuchen. :) – simbabque

4

Haftungsausschluss: Dies ist nur ein Versuch, das Verhalten zu erklären.


Devel :: Vorfachhaken zum Perl debugging API durch das DB-Modell auf. Das ist nur Code. It installs a subDB::DB.

Die große Frage ist, wann wird das ausgeführt. Gemäß perlmod gibt es fünf Blocktypen, die während der Ausführung an bestimmten Punkten ausgeführt werden. Einer von ihnen ist BEGIN, der erste ist.

Betrachten Sie dieses Programm.

use strict; 
use warnings; 
our ($x, $y); 

BEGIN { $x = '42' } 
UNITCHECK { 'unitcheck' } 
CHECK { 'check' } 
INIT { 'init' } 
END { 'end' } 

print "$x\n"; 

Dies wird Ausgang der folgende:

>> trace.pl:8: INIT { 'init' } 
>> trace.pl:3: our ($x, $y); 
>> trace.pl:11: print "$x\n"; 
42 
>> trace.pl:9: END { 'end' } 

So Devel :: Trace sieht den INIT Block und den END Block. Aber warum blockiert der INIT?

oben erwähnt perlmod sagt:

INIT Blöcke nur ausgeführt werden, bevor die Perl Laufzeitausführung beginnt, in "first in, first out" (FIFO) Ordnung.

Offenbar in dieser Phase hat die DB::DB bereits installiert. Ich konnte keine Dokumentation finden, die sagt, wenn eine sub Definition genau ausgeführt wird. Es scheint jedoch, dass es nach BEGIN und vor INIT ist. Daher sieht es nicht, was in der BEGIN vorgeht.

Das Hinzufügen eines BEGIN { $Devel::Trace::TRACE = 1 } an den Anfang der Datei hilft auch nicht.

Ich kramte in der Dokumentation für perldebug und dergleichen, konnte aber keine Erklärung für dieses Verhalten finden. Meine Vermutung ist, dass die Debugger-Schnittstelle über BEGIN überhaupt nicht weiß. Sie werden sehr früh ausgeführt (z. B. perl -c -E 'BEGIN{ say "foo" } say "bar"' wird gedruckt foo.)

+0

Für was es sowieso wert ist. – simbabque

+2

+1, danke für die Erklärung. Dies ist * erste * Zeit, als ich eine Antwort wie "es ist unmöglich" sah. ;) Normalerweise bekommen die "unmöglichen" Fragen Antworten, wie: _es * ist möglich * aber nur durch brutales hacken_ ... :): D – kobame

+3

Ich habe nicht gesagt, dass es unmöglich ist. Ich weiß einfach nicht wie. :-P – simbabque

Verwandte Themen