NAME/НАИМЕНОВАНИЕ
perldebguts - Внутренности отладки в Perl
ОПИСАНИЕ
Это не perldebug, который говорит вам, как использовать отладчик. Это руководство описывает низкоуровневые детали относительно внутренностей отладчика, которые варьируются от трудно до невозможно понимаемых для тех, кто еще не работал плотно с внутренностями Perl. Предостережение лектора.
Внутренние компоненты отладчика (Debugger Internals)
Perl имеет специальные хуки (hooks) отладки во время компиляции и во время выполнения, используемые для создания среды отладки. Эти хуки не следует путать с командами perl -Dxxx, описанными в perlrun, которые используются только, если специальный Perl построен (built) по инструкции в pod странице INSTALL в дереве исходного кода Perl.
Например, когда вы называете встроенную в Perl функцию caller
из пакета DB
, аргументы, которые соответствующий стек фрейм был вызван копируются в @DB::args
массива. Этот механизм включается, когда Perl вызывется с ключом -d. В частности включены следующие дополнительные функции (см. "$^P" in perlvar):
Perl вставляет содержимое
$ENV{PERL5DB}
(илиBEGIN {require 'perl5db.pl'}
если его нет) перед первой строкой вашей программы.Каждый массив
@{"_<$filename"}
держит строки $filename для файла, скомпилированного с Perl. То же самое верно длявыполняемых
(eval
) строк, которые содержат подпрограммы, или которых выполняются в настоящее время. $filename длявыполняемых
строк выглядит как(eval 34)
.Значения в этом массиве магическое в числовом контексте: они сравнивают равенство нулю только, если строка не ломается.
Каждый хэш
%{"_<$filename"}
содержит точки останова и действия с ключом по ее номеру. Отдельные записи (в отличие от всего хэша) устанавливаемы. Perl заботится только о логическом значении правда (true) здесь, хотя значения, используемые perl5db.pl имеют форму"$break_condition\0$action"
.То же самое хранится для исполняемых строк, которые содержат подпрограммы, или которые, выполняются в настоящее время. $filename для
выполняемых
строк выглядит как(eval 34)
.Каждый скаляр
${"_<$filename"}
содержит"_<$filename"
. Это также в случае выполнения строк, которые содержат подпрограммы, или которые в настоящее время выполняются. $filename длявыполняемых
строк выглядит как(eval 34)
.После компиляции каждого
требуемого
файла, но перед выполнением, вызывается процедураDB::postponed(*{"_<$filename"})
, если существуетDB::postponed
. Здесь $filename - это развернутое имятребуемого
файла, как он найдет в значениях (values) %INC.После компиляции каждого
подимени
, проверяется$DB::postponed{subname}
, если она существует. Если этот ключ существует, то вызываетсяDB::postponed(subname)
, если существует процедураDB::postponed
.Поддерживается хэш
%DB::sub
, чьи ключи являются именами подпрограмм и значения которых имеют формуfilename:startline-endline
.filename
имеет форму(eval 34)
для подпрограмм, определенные внутриeval
.Когда выполнение программы достигнет точки, на которой может стоять точка останова, подпрограмма
DB::DB()
вызывается, если любая из переменных$DB::trace
,$DB::single
, или$DB::signal
имеет значение true. Эти переменные не являютсялокализованными
. Эта функция отключена при выполнении внутриDB::DB()
, включая функции, которые вызываются из нее Пока выражение$^D & (1<<30)
имеет значение true.Когда выполнение программы достигает вызова подпрограммы, вместо этого производится вызов
&DB::sub
(args) с$DB::sub
, которая содержит имя вызываемой подпрограммы. (Этого не случиться, если подпрограмма была скомпилирована изDB
пакета.)
Обратите внимание, что если &DB::sub
нужны внешние данные, чтобы он работал, то без нее не возможен вызов подпрограммы. В качестве примера, стандартный отладчик &DB::sub
зависит от переменной $DB::deep
(Он определяет, сколько уровней рекурсии в глубину отладчика вы можете использовать До обязательного перерыва). Если $DB::deep
не определено, вызовы подпрограммы невозможны, хотя существует &DB::sub
.
Написание собственного отладчика (Writing Your Own Debugger)
Переменные среды (Environment Variables)
Переменная среды PERL5DB
может использоваться для определения отладчика. Например, минимальный «рабочий» отладчик (он фактически ничего не делает) состоит из одной строки:
sub DB::DB {}
Его можно легко определить следующим образом:
$ PERL5DB="sub DB::DB {}" perl -d your-script
Можно создать еще один короткий отладчик в одну строку, несколько более полезный:
sub DB::DB {print ++$i; scalar <STDIN>}
Этот отладчик выводит число, которое увеличивается для каждого оператора, с которым он сталкивается и ждет, пока вы нажмете новую строку, прежде чем перейдете к следующему оператору(statement).
Следующий отладчик действительно полезен:
{
package DB;
sub DB {}
sub sub {print ++$i, " $sub\n"; &$sub}
}
Он печатает порядковый номер каждого вызова подпрограммы и имя вызываемой подпрограммы. Обратите внимание, что &DB::sub
компилируется в Пакет DB
с помощью директивы package
.
Когда он запускается, отладчик считывает ваш файл rc (./.perldb или ~/.perldb под Unix), который может устанавливать важные параметры. (Здесь также можно определить подпрограмму (&afterinit
), она выполняется после того как отладчик завершит свою инициализацию.)
После считывания файла rc отладчик считывает переменную окружения PERLDB_OPTS и использует ее для установки параметров отладчика. СОДЕРЖАНИЕ Содержимое этой переменной обрабатывается так, как если бы они были аргументом o ...
команды отладчика (q.v. в "Configurable Options" in perldebug) (q.v. в "Настраиваемые параметры" in perldebug).
Внутренние переменные отладчика (Debugger Internal Variables)
В дополнение к упомянутым выше переменным, связанным с файлом и подпрограммой, отладчик также поддерживает различные магические внутренние переменные.
@DB::dbline
является псевдонимом для@{"::_<current_file"}
, который содержит строки выбранного в данный момент файла (скомпилированного Perl), либо явно выбранный с помощью команды отладчикаf
или неявно по потоку исполнения.Значения в этом массиве являются магическими в числовом контексте: они сравнивают равенство нулю только в том случае, если строка не является хрупкой.(they compare equal to zero only if the line is not breakable.)
%DB::dbline
является псевдонимом для%{"::_<current_file"}
, который содержит точки останова и действия, заданные номером строки в выбранный в данный момент файл, либо явно выбранный с помощью команды отладчикаf
, или неявно по потоку выполнения.Как отмечалось ранее, отдельные записи (в отличие от всего хеша) могут устанавливаться. Perl только заботится о булевой истине здесь, хотя значения, используемые perl5db.pl имеют вид
"$break_condition\0$action"
.
Функции настройки отладчика
Некоторые функции предусмотрены для упрощения настройки.
См. "Configurable Options" in perldebug ("Настраиваемые параметры" in perldebug) для описания параметров, проанализированных
DB::parse_options(string)
.DB::dump_trace(skip[,count])
пропускает указанное количество кадров и возвращает список, содержащий информацию о вызывающих кадрах (все из них, еслиcount
отсутствует). Каждая запись является ссылкой на хэш с ключамиcontext
(либо.
,$
, or@
),sub
(имя подпрограммы или сведения оeval
),args
(undef
или ссылка на массив),file
, иline
.DB::print_trace(FH, skip[, count[, short]])
печатает отформатированную информацию о кадрах вызывающего (caller frames). Последние две функции могут быть удобными в качестве аргументов командам<
,<<
.
Обратите внимание, что любые переменные и функции, не документированные в эти манах (или в perldebug) рассматриваются только для внутреннего использования и, как таковые, могут быть изменены без предварительного уведомления.
Примеры вывода списка кадров (Frame Listing Output Examples)
Опцию frame
можно использовать для управления выходом кадра информации. Например, сравните этот вывод трейса:
$ perl -de 42
Дамп стека во время смерти включен за пределами проверки. (Stack dump during die enabled outside of evals.)
Loading DB routines from perl5db.pl patch level 0.94
Emacs support available.
Enter h or 'h h' for help.
main::(-e:1): 0
DB<1> sub foo { 14 }
DB<2> sub bar { 3 }
DB<3> t print foo() * bar()
main::((eval 172):3): print foo() + bar();
main::foo((eval 168):2):
main::bar((eval 170):2):
42
с этим, как только o
ption frame=2
был установлен:
DB<4> o f=2
frame = '2'
DB<5> t print foo() * bar()
3: foo() * bar()
entering main::foo
2: sub foo { 14 };
exited main::foo
entering main::bar
2: sub bar { 3 };
exited main::bar
42
В качестве демонстрации ниже мы приведем трудоемкий список в результате установки переменной окружения PERLDB_OPTS
на значение f=n N
, и запуск perl -d -V из командной строки. Показано, что примеры, использующие различные значения n
дают вам почувстовать разницу между настройками. Хотя это может быть длинно, это не полный список, а только выдержки.
-
entering main::BEGIN entering Config::BEGIN Package lib/Exporter.pm. Package lib/Carp.pm. Package lib/Config.pm. entering Config::TIEHASH entering Exporter::import entering Exporter::export entering Config::myconfig entering Config::FETCH entering Config::FETCH entering Config::FETCH entering Config::FETCH
-
entering main::BEGIN entering Config::BEGIN Package lib/Exporter.pm. Package lib/Carp.pm. exited Config::BEGIN Package lib/Config.pm. entering Config::TIEHASH exited Config::TIEHASH entering Exporter::import entering Exporter::export exited Exporter::export exited Exporter::import exited main::BEGIN entering Config::myconfig entering Config::FETCH exited Config::FETCH entering Config::FETCH exited Config::FETCH entering Config::FETCH
-
in $=main::BEGIN() from /dev/null:0 in $=Config::BEGIN() from lib/Config.pm:2 Package lib/Exporter.pm. Package lib/Carp.pm. Package lib/Config.pm. in $=Config::TIEHASH('Config') from lib/Config.pm:644 in $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 in $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from li in @=Config::myconfig() from /dev/null:0 in $=Config::FETCH(ref(Config), 'package') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'baserev') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'PERL_VERSION') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'PERL_SUBVERSION') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'osname') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'osvers') from lib/Config.pm:574
-
in $=main::BEGIN() from /dev/null:0 in $=Config::BEGIN() from lib/Config.pm:2 Package lib/Exporter.pm. Package lib/Carp.pm. out $=Config::BEGIN() from lib/Config.pm:0 Package lib/Config.pm. in $=Config::TIEHASH('Config') from lib/Config.pm:644 out $=Config::TIEHASH('Config') from lib/Config.pm:644 in $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 in $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/ out $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/ out $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 out $=main::BEGIN() from /dev/null:0 in @=Config::myconfig() from /dev/null:0 in $=Config::FETCH(ref(Config), 'package') from lib/Config.pm:574 out $=Config::FETCH(ref(Config), 'package') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'baserev') from lib/Config.pm:574 out $=Config::FETCH(ref(Config), 'baserev') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'PERL_VERSION') from lib/Config.pm:574 out $=Config::FETCH(ref(Config), 'PERL_VERSION') from lib/Config.pm:574 in $=Config::FETCH(ref(Config), 'PERL_SUBVERSION') from lib/Config.pm:574
-
in $=main::BEGIN() from /dev/null:0 in $=Config::BEGIN() from lib/Config.pm:2 Package lib/Exporter.pm. Package lib/Carp.pm. out $=Config::BEGIN() from lib/Config.pm:0 Package lib/Config.pm. in $=Config::TIEHASH('Config') from lib/Config.pm:644 out $=Config::TIEHASH('Config') from lib/Config.pm:644 in $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 in $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/E out $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/E out $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 out $=main::BEGIN() from /dev/null:0 in @=Config::myconfig() from /dev/null:0 in $=Config::FETCH('Config=HASH(0x1aa444)', 'package') from lib/Config.pm:574 out $=Config::FETCH('Config=HASH(0x1aa444)', 'package') from lib/Config.pm:574 in $=Config::FETCH('Config=HASH(0x1aa444)', 'baserev') from lib/Config.pm:574 out $=Config::FETCH('Config=HASH(0x1aa444)', 'baserev') from lib/Config.pm:574
-
in $=CODE(0x15eca4)() from /dev/null:0 in $=CODE(0x182528)() from lib/Config.pm:2 Package lib/Exporter.pm. out $=CODE(0x182528)() from lib/Config.pm:0 scalar context return from CODE(0x182528): undef Package lib/Config.pm. in $=Config::TIEHASH('Config') from lib/Config.pm:628 out $=Config::TIEHASH('Config') from lib/Config.pm:628 scalar context return from Config::TIEHASH: empty hash in $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 in $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/Exporter.pm:171 out $=Exporter::export('Config', 'main', 'myconfig', 'config_vars') from lib/Exporter.pm:171 scalar context return from Exporter::export: '' out $=Exporter::import('Config', 'myconfig', 'config_vars') from /dev/null:0 scalar context return from Exporter::import: ''
Во всех случаях, показанных выше, отступ строки показывает дерево вызовов. Если бит 2 frame
установлен, строка будет успешно напечатана при выходе из подпрограммы. Если бит 4 установлен, аргументы печатаются наряду с информацией о вызывающей функции Если бит 8 установлен, аргументы напечатаются, даже если они связаны или ссылаются. (even if they are tied or references.) Если бит 16 установлен, то возвращаемое значение также печатается.
Когда пакет компилируется, строка, подобная этой
Package lib/Carp.pm.
Печатается с правильным отступом.
Отладка регулярных выражений
Есть два способа включить вывод отладки для регулярных выражений.
Если ваш perl скомпилирован с помощью -DDEBUGGING
, вы можете использовать флаг -Dr в командной строке.
В противном случае вы можете использовать use re 'debug'
, который работает и во время компиляции и во время выполнения. Начиная с Perl 5.9.5, эта прагма имеет лексическую область видимости.
Вывод лога во время компиляции (Compile-time Output)
Вывод отладки во время компиляции выглядит так:
Compiling REx '[bc]d(ef*g)+h[ij]k$'
size 45 Got 364 bytes for offset annotations.
first at 1
rarest char g at 0
rarest char d at 0
1: ANYOF[bc](12)
12: EXACT <d>(14)
14: CURLYX[0] {1,32767}(28)
16: OPEN1(18)
18: EXACT <e>(20)
20: STAR(23)
21: EXACT <f>(0)
23: EXACT <g>(25)
25: CLOSE1(27)
27: WHILEM[1/1](0)
28: NOTHING(29)
29: EXACT <h>(31)
31: ANYOF[ij](42)
42: EXACT <k>(44)
44: EOL(45)
45: END(0)
anchored 'de' at 1 floating 'gh' at 3..2147483647 (checking floating)
stclass 'ANYOF[bc]' minlen 7
Offsets: [45]
1[4] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 5[1]
0[0] 12[1] 0[0] 6[1] 0[0] 7[1] 0[0] 9[1] 8[1] 0[0] 10[1] 0[0]
11[1] 0[0] 12[0] 12[0] 13[1] 0[0] 14[4] 0[0] 0[0] 0[0] 0[0]
0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 18[1] 0[0] 19[1] 20[0]
Omitting $` $& $' support.
Первая строка показывает предварительно скомпилированную форму регулярного выражения. Вторая показывает размер скомпилированной формы (в произвольных единицах, обычно 4-байтные слова) и общее количество байт, выделенных для таблицы смещения/длины, обычно 4+размер
* 8 (offset/length table, usually 4+size
*8). Следующая строка показывает метку id первого узла, с которым выполнилось сопоставление (первого найденного узла).
Привязанный 'de' к 1 плавающей 'gh' в 3..2147483647 (проверка плавающей)
Stclass 'ANYOF [bc]' minlen 7
(anchored 'de' at 1 floating 'gh' at 3..2147483647 (checking floating)
stclass 'ANYOF[bc]' minlen 7)
cтрока (разделенная на две строки) содержит информацию оптимизатора. В показанном примере оптимизатор обнаружил, что совпадение должно содержать подстроку de
со смещением 1 плюс подстрока gh
при некотором смещении между 3 и бесконечностью. Более того, при проверке на эти подстроки (чтобы отказаться от невозможных совпадений быстро), Perl проверит для подстроки gh
перед проверкой подстроки de
. Оптимизатор также может использовать знания о том, что начало матча (на first
id) с символьным классом и строка короче 7 символов не может быть найдена.
Поля, представляющие интерес, могут отображаться в этой строке:
anchored
STRINGat
POSfloating
STRINGat
POS1..POS2-
См. Выше.
matching floating/anchored
-
Какую подстроку проверить в первую очередь.
minlen
-
Минимальная длина поиска(match).
stclass
TYPE-
Тип первого совпадающего узла.
noscan
-
Не сканируйте найденные подстроки.
isall
-
Означает, что информация оптимизатора - это все, что содержит регулярное выражение, и, таким образом, нет необходимости вводить регулярное выражение вообще (does not need to enter the regex engine at all.)
GPOS
-
Установите, если шаблон содержит
\G
. plus
-
Установите, если шаблон начинается с повторяющегося символа (как в
x+y
). implicit
-
Установите, если шаблон начинается с
.*
. with eval
-
Установите, если шаблон содержит eval-группы, такие как
(?{ code })
и(??{ code })
. якорный(ТИП)
(anchored(TYPE)
)-
Если шаблон может соответствовать нескольким местам, с
TYPE
будучиBOL
, С<MBOL> или С<GPOS>. Смотрите таблицу ниже.
Если подстрока, как известно, должна соответствует только в конце строки , то за ней нужно ставить символ $
, как в плавающий 'k'$
(floating 'k'$
).
Информация для оптимизатора используется, чтобы избежать ввода (медленного) регекс двигателя для строк, которые не будут соответствовать определенно. Если флаг isall
задан, вызов обработчика регулярных выражений можно избежать даже когда оптимизатор нашел соответствующее место для поиска.
Раздел про оптимизатор выше представляет собой список узлов (nodes) из скомпилированных форм регекса. Каждая строка имеет формат
id: ТИП ОПЦИОНАЛЬНАЯ-ИНФОРМАЦИЯ (следующий-ид)
id: TYPE OPTIONAL-INFO (next-id)
Типы узлов (Types of Nodes)
Ниже приведены возможные типы, с кратким описанием:
# ТИП описание-аргумента [число-аргументов] [прыжок-в-длину-длина] ОПИСАНИЕ
# TYPE arg-description [num-args] [longjump-len] DESCRIPTION
# Точки выхода
# Exit points
END no Конец программы.
SUCCEED no Вернуться из подпрограммы, в основном. (Return from a subroutine, basically.)
# Якоря:
BOL no Найдет "" в начале строки.
MBOL no То же,предполагая мультистроку.
SBOL no То же,предполагая одностроку. (Same, assuming singleline.)
EOS no Найдет "" в конце строки. (string)
EOL no Найдет "" в конце линии. (line)
MEOL no То же,предполагая мультистроку.
SEOL no То же,предполагая одностроку.
BOUND no Найдет "" при любом использовании границы слова
при родной семантике кодировки для не-utf8
BOUNDL no Найдет "" в любой локальной границе слова ( Match "" at any locale word boundary)
BOUNDU no Найдет "" в любой локальной границе слова
используя семантику Юникода
BOUNDA no Найдет "" в любой локальной границе слова используя ASCII
семантику
NBOUND no Найдет "" в любой не-границе слова используя
родные не-UTF кодировку (native charset semantics for non-utf8)
NBOUNDL no Найдет "" в любой локальной не-границе слова
NBOUNDU no Найдет "" в любой не-границе слова используя
семантику Юникода
NBOUNDA no Найдет "" в любой не-границе слова используя
ASCII семантику
GPOS no Совпадения, в которых остановились последние m//g.
# [Специальные] альтернативы:
REG_ANY no Соответствует любому символу (кроме символа новой строки).
SANY no Соответствует любому одному символу.
CANY no Соответствует любому одному байту.
ANYOF sv Сопоставить символ в (или не в) этого
класса, только односимвольное соответствие
ANYOF_WARN_SUPER sv Сопоставить символ в (или не в) этого
класса, кидает ворнинги (если включено) после нахождения
Char выше Unicode максимального юникода (max);
(Match character in (or not in) this
class, warn (if enabled) upon matching a
char above Unicode max;)
ANYOF_SYNTHETIC sv Синтетический стартовый класс (Synthetic start class)
POSIXD none Некоторым [[:class:]] под /d;
ставит один флаг (the FLAGS field gives which one)
POSIXL none Некоторым [[:class:]] под /l;
ставит один флаг (the FLAGS field gives which one)
POSIXU none Некоторым [[:class:]] под /u;
ставит один флаг (the FLAGS field gives which one)
POSIXA none Некоторым [[:class:]] под /a;
ставит один флаг (the FLAGS field gives which one)
NPOSIXD none дополнение класса POSIXD, [[:^class:]] (его отрицание)
NPOSIXL none дополнение класса POSIXL, [[:^class:]]
NPOSIXU none дополнение класса POSIXU, [[:^class:]]
NPOSIXA none дополнение класса POSIXA, [[:^class:]]
CLUMP no Находит расширенную последовательность графема кластера -
(специальное юникодной комбинации - примечание переводчика)
(Match any extended grapheme cluster sequence)
# Альтернатива (Alternation)
# BRANCH Совокупность веток(branches), образующих единый выбор
# связанный вместе с их "следующими" указателями, так
# приоритет предотвращает все, что объединено в
# любых отдельных ветвях. "Следующий" указатель последней
# ВЕТКИ в моменты выбора следует за
# всем выбором. Это также, где в финале "далее"
# указатель каждой отдельной точки ветвления; каждая ветвь
# начинается с узлом операнда узла ВЕТКИ.
#
BRANCH node Найдет эту альтернативу или следующую ...(Match this alternative, or the next)
# Обратный указатель (Back pointer)
# BACK Нормальные указатели "next" все неявно указывают вперед;
# BACK существует, чтобы сделать возможной структуру цикла.
# not used
BACK no Найдет "", "next" ptr показывает назад.
# Literals
EXACT str Соответствует этой строке (ей предшествует длина). (Match this string (preceded by length).)
EXACTF str Найдет эту не-UTF-8 строку (нет
гарантии сложения (to be folded)) используя /id правил
(w/len).
EXACTFL str Найдёт эту строку (нет
гарантии сложения) используя /il правила (w/len).
EXACTFU str Найдёт эту строку (сложенный iff в UTF-8,
длина при складывании не изменяется, если не
в UTF-8) используя /iu правила (w/len).
EXACTFA str Найдёт эту строку (нет
гарантии сложения) используя /iaa правила (w/len).
EXACTFU_SS str Найдёт эту строку (сложенный iff в UTF-8,
длина в сложенном состоянии может измениться, даже если не
в UTF-8) используя /iu правила (w/len).
EXACTFU_TRICKYFOLD str Найдет эту свернутую(folded) строку UTF-8, используя /iu
правила
# Ничего не делать
NOTHING no Соответствует пустой строке.
# Вариант выше, который ограничивает группу, тем самым останавливает оптимизацию
TAIL no Соответствует пустой строке. Может прыгать сюда из-
за пределов (Match empty string. Can jump here from
outside).
# Циклы
# STAR,PLUS '?', И сложные '*' и '+', реализованы как
# круговые BRANCH структуры с использованием BACK. Простые случаи
# (один символ в поиске (per match)) реализованы с помощью STAR
# и PLUS для скорости и минимизации рекурсивных погружений (plunges).
#
STAR node Найдет эту (простую) вещь 0 или более раз
PLUS node Найдет эту (простую) вещь 1 или более раз
CURLY sv 2 Найдет эту (простую) вещь {n,m} раз
CURLYN no 2 Захватит следующую после этого простую вещь (сapture next-after-this simple thing)
CURLYM no 2 Захватит эту средне-сложную вещь {n,m} раз.
CURLYX sv 2 Найдет эту сложную вещь {n,m} раз.
# Этот терминатор(разделитель) создает структуру цикла для
WHILEM no Делайте кудрявую обработку и смотрите, остались ли данные для поиска.
(Do curly processing and see if rest matches.0
# Связанные с буфером
# OPEN,CLOSE,GROUPP ...нумеруются во время компиляции.
OPEN num 1 Отметьте эту точку ввода как начало #n.
CLOSE num 1 Аналогично OPEN.
REF num 1 Соответствует некоторой уже найденной строке
REFF num 1 Найти уже найденную строку, свернутую
с использованием встроенной семантики кодировки для не-
utf8
REFFL num 1 Найти уже найденную строку, свернутую в
loc.
REFFU num 1 Найти уже найденную строку, свернутую
с использованием семантики Unicode для non-utf8
REFFA num 1 Найти уже найденную строку, свернутую
с использованием семантики Unicode для non-utf8, но
смешанную с ASCII, не-ASCII
# Именованные ссылки. Код в regcomp.c предполагает, что все они после
# пронумерованных ссылок
NREF no-sv 1 Найдет некоторую уже найденную строку
NREFF no-sv 1 Найти уже найденную строку, свернутую
с использованием встроенной семантики кодировки для не-
utf8
NREFFL no-sv 1 Найти уже найденную строку, свернутую в
loc.
NREFFU num 1 Найти уже найденную строку, свернутую
с использованием семантики Unicode для non-utf8
NREFFA num 1 Найти уже найденную строку, свернутую
с использованием семантики Unicode для non-utf8, но
смешанную с ASCII, не-ASCII
IFMATCH off 1 2 Успешно, если следующие совпадают.
UNLESSM off 1 2 Сбой, если следующие совпадают.
SUSPEND off 1 1 "Независимое" sub-RE (подрегулярное выражение).
IFTHEN off 1 1 Переключатель, которому должен предшествовать переключатель. (Switch, should be preceded by switcher.)
GROUPP num 1 Где находится группа. (Whether the group matched.)
# Поддержка длинных RE
LONGJMP off 1 1 Прыгай далеко.
BRANCHJ off 1 1 BRANCH с длинным смещением.
# Тяжелый рабочий (The heavy worker)
EVAL evl 1 Выполнить некоторый Perl-код.
# Модификаторы
MINMOD no Следующий оператор не жадный.
LOGICAL no Следующий опкод должен устанавливать только флаг.
# Это еще не используется
RENUM off 1 1 Группа с независимой нумерацией.
# Связанные темы
# Ведёт себя так же, как A|LIST|OF|WORDS. Варианты '..C'
# имеют встроенные данные charclass (только ascii), где 'C' хранит его
# в составе.
TRIE trie 1 Найдет много EXACT(F[ALU]?)? один раз (at once).
flags==type
TRIEC trie То же, что и TRIE, но со встроенным charclass
AHOCORASICK trie 1 Aho Corasick stclass. flags==type
AHOCORASICKC trie То же, что и AHOCORASICK, но со встроенным charclass
# Подпрограммы регулярных выражений (Regex Subroutines)
GOSUB num/ofs 2L рекурсия к родительскому arg1 на (подписанных) ofs arg2 (recurse to paren arg1 at (signed) ofs)
GOSTART no рекурсия к началу шаблона (recurse to start of pattern)
# Специальные условия
NGROUPP no-sv 1 Соответствовала ли группа. (Whether the group matched.)
INSUBP num 1 Будем ли мы в конкретной рекурсии.
DEFINEP none 1 Никогда не выполняйте непосредственно.
# Глаголы с отступами (Backtracking Verbs)
ENDLIKE none Используется только для поля типа глагола (Used only for the type field of verbs)
OPFAIL none Тоже, что и (?!)
ACCEPT parno 1 Принимает текущую найденную строку. (Accepts the current matched string.)
# Глаголы с аргументами (Verbs With Arguments)
VERB no-sv 1 Используется только для поля типа глаголов (verbs)
PRUNE no-sv 1 Образец терпит неудачу в этой начальной точке, если нет возврата через этот
(Pattern fails at this startpoint if no-
backtracking through this)
MARKPOINT no-sv 1 Нажмите текущее местоположение для отката путем вырезания. (Push the current location for rollback by
cut.)
SKIP no-sv 1 При отказе пропустить вперед (до отметки) перед повторной попыткой (On failure skip forward (to the mark)
before retrying)
COMMIT no-sv 1 Шаблон выходит из строя, если возврат (Pattern fails outright if backtracking
through this)
CUTGROUP no-sv 1 При сбое перейдите к следующему чередованию в группе (On failure go to the next alternation in
the group)
# Контролируйте, что нужно держать в $&.
KEEPS no $& начинается здесь.
# Новые charclass(классы символов), похожие на шаблоны (New charclass like patterns)
LNBREAK none создать шаблон начала строки (generic newline pattern)
# СПЕЦИАЛЬНЫЕ РЕГУЛЯРКИ (SPECIAL REGOPS)
# Это не совсем узел, а оптимизированный кусок "длинного" узла #. Для упрощения отладки, мы отмечаем его, как будто это был узел OPTIMIZED off Заполнителя для сброса.
# Специальные свойства операции(opcode), которые не код(opcode) в скомпилированной программе # никогда не будет этого типа. Таким образом, он может использоваться в качестве значения флага, что # никакие другие операции(opcode) не видно. END используется аналогичным образом, в том, что END # узел не может быть оптимизирован. Так что END предполагает "неоптимизируемость" "unoptimizable" и PSEUDO # в смысле "не видел ничего, чтобы оптимизировать". PSEUDO off Pseudo код для внутреннего использования.
Следующим оптимизатором информация представляет собой дамп смещение/длина стола, здесь разделены на несколько линий:
Offsets: [45]
1[4] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 5[1]
0[0] 12[1] 0[0] 6[1] 0[0] 7[1] 0[0] 9[1] 8[1] 0[0] 10[1] 0[0]
11[1] 0[0] 12[0] 12[0] 13[1] 0[0] 14[4] 0[0] 0[0] 0[0] 0[0]
0[0] 0[0] 0[0] 0[0] 0[0] 0[0] 18[1] 0[0] 19[1] 20[0]
Первая строка указывает на то, что таблица смещений/длин содержит 45 записей. Каждая запись является парой чисел(integers), обозначается смещение[длина]
(offset[length]
.). Записи нумеруются начиная с 1, поэтому запись #1 вот это 1[4]
и запись #12 это С<5[1]>. С<1[4]> указывает, что узел, обозначенный как 1:
(1: что-нибудь из[до н. э.]
)(the 1: ANYOF[bc]
) начинается в позиции символа 1 в предварительно скомпилированном виде регулярного выражения, и имеет длину 4 символа. С<5[1]> в положении 12 указывает, что узел, обозначенный как c<12:> (12: точные <д>
)(the 12: EXACT <d>
) начинается на символ 5 в предварительно скомпилированном виде регулярного выражения, и имеет длину 1 символ. С<12[1]> в позиции 14 указывает, что узел, обозначенный как 14:
(14: CURLYX[0] {1,32767}
) начинается в позиции знака 12 В предварительно скомпилированном виде регулярного выражения, и имеет длину 1 символ - - -, что является, оно соответствует +
символ в предварительно скомпилированном регулярном выражении (in the precompiled regex)
С<0[0]> элементы указывают на то, что нет соответствующего узла.
Вывод времени выполнения (Run-time Output)
В первую очередь, когда происходит совпадение, может не быть времени на output даже если включена отладка. Это означает, что регулярное выражение никогда не вошло , и поэтому вся работа была сделана оптимизатором.
Если регулярное выражение было введено, то на выходе может выглядеть следующим образом:
Matching '[bc]d(ef*g)+h[ij]k$' against 'abcdefg__gh__'
Setting an EVAL scope, savestack=3
2 <ab> <cdefg__gh_> | 1: ANYOF
3 <abc> <defg__gh_> | 11: EXACT <d>
4 <abcd> <efg__gh_> | 13: CURLYX {1,32767}
4 <abcd> <efg__gh_> | 26: WHILEM
0 out of 1..32767 cc=effff31c
4 <abcd> <efg__gh_> | 15: OPEN1
4 <abcd> <efg__gh_> | 17: EXACT <e>
5 <abcde> <fg__gh_> | 19: STAR
EXACT <f> can match 1 times out of 32767...
Setting an EVAL scope, savestack=3
6 <bcdef> <g__gh__> | 22: EXACT <g>
7 <bcdefg> <__gh__> | 24: CLOSE1
7 <bcdefg> <__gh__> | 26: WHILEM
1 out of 1..32767 cc=effff31c
Setting an EVAL scope, savestack=12
7 <bcdefg> <__gh__> | 15: OPEN1
7 <bcdefg> <__gh__> | 17: EXACT <e>
restoring \1 to 4(4)..7
failed, try continuation...
7 <bcdefg> <__gh__> | 27: NOTHING
7 <bcdefg> <__gh__> | 28: EXACT <h>
failed...
failed...
Наиболее существенная информация в выводе о том, что узел (node) скомпилированного регулярного выражения в настоящее время тестируется в отношении к целевой строке. Формат этих строк
STRING-OFFSET <PRE-STRING> <POST-STRING> |ID: TYPE
Информация о ТИПЕ (TYPE) форматируется относительно уровне трекинга (backtracking level). Другая информация об инциденте появляется и пересекается внутри.
Использования Памяти при Отладке в Perl (Debugging Perl Memory Usage)
Perl-это распутный бездельник, когда дело доходит до использования памяти. Говорят, чтобы оценить использование памяти в Perl нужно подразумевать разумный алгоритм выделения памяти, умножить эту оценку на 10, и хотя вы можете промазать, но по крайней мере, вы не будете так удивлены. Это не совсем так, но может обеспечить хорошее понимание о том, что происходит.
Предположим, что целое число(integer) не может принимать меньше 20 байт памяти, a плавающее(float) не может занимать менее 24 байт, а строка(string) не может занимать меньше 32 байта (все эти примеры предполагают 32-разрядные архитектуры, результат немного хуже на 64-битных архитектурах). Если к переменной осуществляется доступ двумя из трех различных способов (для которых требуется целое число(integer), плавающее(float), или строку(string)), объем памяти возможно увеличить еще на 20 байт. Неаккуратная реализация функции malloc(3) может раздуть эти значения драматически.
На противоположном конце шкалы, объявление
sub foo;
может потребовать до 500 байт памяти, в зависимости от версии языка Perl под которым вы запускаетесь.
Анекдотические оценки наворотов кода для копиляции (source-to-compiled) предполагают 8-кратное увеличение. Это означает, что скомпилированная форма разумного (хорошо скомментированного, с правильно отступом и т. д.) кода возьмёт принял примерно в восемь раз больше места в памяти, чем код на диске.
Переключатель командной строки -DL устарел начиная с 5.6.0 (он был доступен, только если Perl был построен c -DDEBUGGING
). Этот ключ использовался для отслеживания распределения памяти в Perl и возможной утечки памяти. В наши дни для отладки использования malloc вместо этого предлагаются такие инструменты, как Purify или valgrind. Смотрите также "PERL_MEM_LOG" in perlhacktips.
Один из способов узнать, сколько памяти используется данными Perl структуры - установить модуль Devel::Size из CPAN: он дает вам минимальное количество байтов, необходимых для хранения определенных данных. Помните о различии между size() и total_size ().
Если Perl был скомпилирован с использованием malloc Perl, вы можете проанализировать использования памяти Perl, задав $ENV{PERL_DEBUG_MSTATS}.
С помощью $ENV{PERL_DEBUG_MSTATS}
Если ваш perl использует malloc() и был скомпилирован с необходимые переключатели (это значение по умолчанию), то после этого он напечатает память статистики использования после компиляции кода, когда $ENV{PERL_DEBUG_MSTATS} > 1
, и до окончания программы, когда $ENV{PERL_DEBUG_MSTATS} >= 1
. Формат отчета похож на следующий пример:
$ PERL_DEBUG_MSTATS=2 perl -e "require Carp"
Статистика выделения памяти после компиляции: (buckets 4(4)..8188(8192)
14216 free: 130 117 28 7 9 0 2 2 1 0 0
437 61 36 0 5
60924 used: 125 137 161 55 7 8 6 16 2 0 1
74 109 304 84 20
Total sbrk(): 77824/21:119. Odd ends: pad+heads+chain+tail: 0+636+0+2048.
Статистика выделения памяти после выполнения: (buckets 4(4)..8188(8192)
30888 free: 245 78 85 13 6 2 1 3 2 0 1
315 162 39 42 11
175816 used: 265 176 1112 111 26 22 11 27 2 1 1
196 178 1066 798 39
Total sbrk(): 215040/47:145. Odd ends: pad+heads+chain+tail: 0+2192+0+6144.
Можно попросить такую статистику в произвольных точках при выполнении с использованием функции mstat() вне стандарта модуля Devel::Peek.
Вот некоторые объяснения этого формата:
buckets SMALLEST(APPROX)..GREATEST(APPROX)
-
В Perl функция malloc() использует распределение по периодам. Каждый запрос округляется до ближайшего размера бакета, и бакет извлекается из пула бакетов такого размера.
В приведенной выше строке описаны пределы используемых в настоящее время бакетов. Каждый бакет имеет два размера: объем памяти и максимальный размер пользовательских данных, которые могут поместиться в бакет. Предположим, в приведенном выше примере, чтобы наименьший бакет было размером 4. Самый большой бакет имел бы полезный размер 8188, и след памяти был бы 8192.
В Perl, скопилирлованном для отладки, некоторые бакеты могут иметь отрицательное использование размера. Это означает, что эти бакеты не могут (и не будут) использоваться. Для больших контейнеров объем памяти может быть на одну страницу больше чем квадрат 2(power of 2). Если это так, соответствующая сила двух печатает в поле
APPROX
выше. - Свободный/используемый (Free/Used)
-
1 или 2 строки чисел, которые соответствуют числу пакетов (бакетов) каждый размер между
НАИМЕНЬШИМ
иНАИБОЛЬШИМ
. В первой строке, размеры (следы памяти) пакетов сильны из двух--или, возможно, на одну страницу больше. Во второй строке, если имеется, следы памяти пакетов находятся между следами памяти из двух пакетов "выше".Например, предположим, что в предыдущем примере, следы памяти(memory footprints) были
свободно: 8 16 32 64 128 256 512 1024 2048 4096 8192 4 12 24 48 80
С не-
DEBUGGING
perl, пачки (buckets) начинающиеся с128
имеют 4-байтовые накладные расходы, и, таким образом, 8192-длинная пачка может занять до 8188-байт. Total sbrk(): SBRKed/SBRKs:CONTINUOUS
-
Первые два поля дают общий объем памяти в Perl сбрк(2)Эд (есс-сломался? :-) и количество сбрк(2)использованных. Третий номер то, что Perl думает о продолжительном возвращении кусками. Пока это число является положительным, malloc() будет предполагать, что такое возможно что сбрк(2) будет обеспечивать продолженную память.
Память, выделенная с помощью внешних библиотек не учитывается.
pad: 0
-
Количество sbrk(2)(linux комманда - изменить размер сегмента данных) памяти, необходимой для поддержания выравненных пачек(needed to keep buckets aligned).
heads: 2192
-
Хотя память больших пачках хранится внутри пачки(bucket), для меньших пакетов она хранится в отдельных зонах. Это поле дает общую площадь этих участков.
chain: 0
-
функции malloc() может хотеть разделить большой пакет на мелкие пакеты. Если только часть умершего пакета осталась неразделенная, остальные хранятся как элемент связанного списка. Это поле дает общий размер этих блоков.
tail: 6144
-
Чтобы свести к минимуму количество сбрк(2)с(sbrk(2)s) функциями malloc() запрашивает больше памяти. Это поле дает Размер еще неиспользованной части, которая сбрк(2)Эд(sbrk(2)ed), собрана но никогда не трогалась.
СМОТРЕТЬ ТАКЖЕ
perldebug, perlguts, perlrun re, and Devel::DProf.
ПЕРЕВОДЧИКИ
Николай Мишин
<mi@ya.ru>