Как убедить Devel:: Trace распечатать инструкции BEGIN-блока?
У вас есть простой script p.pl:
use strict;
use warnings;
our $x;
BEGIN {
$x = 42;
}
print "$x\n";
Когда я запускаю его как:
perl -d:Trace p.pl
печатает:
>> p.pl:3: our $x;
>> p.pl:7: print "$x\n";
42
как печатать также инструкции BEGIN block, например. $x = 42;
?
Поскольку мое намерение не ясно, добавив пояснение:
Ищете ЛЮБОЙ способ распечатывать утверждения при запуске perl script (например, Devel:: Trace), но включая инструкции в блоке BEGIN.
Ответы
Ответ 1
Это очень возможно. Установите $DB::single
в раннем блоке BEGIN
.
use strict;
use warnings;
our $x;
BEGIN { $DB::single = 1 }
BEGIN {
$x = 42;
}
print "$x\n";
$DB::single
- это отладочная переменная, используемая для определения того, будет ли функция DB::DB
вызываться в каждой строке. На этапе компиляции это обычно неверно, но вы можете установить его на этапе компиляции в блоке BEGIN
.
Этот трюк также полезен для установки точки останова внутри блока BEGIN
, когда вы хотите отлаживать код времени компиляции в стандартном отладчике.
Ответ 2
Отказ от ответственности: это всего лишь попытка объяснить поведение.
Devel:: Trace подключается к API отладки Perl через модель DB. Это всего лишь код. Он устанавливает суб DB::DB
.
Большой вопрос: когда это выполняется. Согласно perlmod, существует пять типов блоков, которые выполняются в определенных точках во время выполнения. Один из них BEGIN
, который является первым.
Рассмотрим эту программу.
use strict;
use warnings;
our ($x, $y);
BEGIN { $x = '42' }
UNITCHECK { 'unitcheck' }
CHECK { 'check' }
INIT { 'init' }
END { 'end' }
print "$x\n";
В результате вы получите следующее:
>> trace.pl:8: INIT { 'init' }
>> trace.pl:3: our ($x, $y);
>> trace.pl:11: print "$x\n";
42
>> trace.pl:9: END { 'end' }
Итак, Devel:: Trace видит блок INIT
и блок END
. Но почему блок INIT
?
Вышеупомянутый perlmod говорит:
Блоки INIT запускаются непосредственно перед началом выполнения Perl, в порядке "первый вход, первый выход" (FIFO).
По-видимому, на этой фазе DB::DB
уже установлен. Я не мог найти документацию, которая говорит, когда определение sub
выполняется точно. Однако, кажется, это после BEGIN
и до INIT
. Следовательно, он не видит, что происходит в BEGIN
.
Добавление BEGIN { $Devel::Trace::TRACE = 1 }
в начало файла также не помогает.
Я порылся в документации для perldebug и подобных, но не смог найти объяснения этого поведения. Я предполагаю, что интерфейс отладчика вообще не знает о BEGIN
. Они выполняются очень рано в конце (рассмотрите, например, perl -c -E 'BEGIN{ say "foo" } say "bar"'
, напечатает foo.)