內容

名稱

perldebguts - Perl 除錯核心

說明

這不是 perldebug,它會告訴你如何使用偵錯器。此手冊頁面描述偵錯器內部有關低階層級的詳細資訊,對於任何對 Perl 內部結構不十分熟悉的人來說,這些資訊從困難到不可能理解。讀者請自行斟酌。

偵錯器內部結構

Perl 在編譯時間和執行時間具有特殊的偵錯掛鉤,用於建立偵錯環境。這些掛鉤不要與 perlrun 中所述的 perl -Dxxx 命令混淆,後者只有在按照 Perl 原始碼樹中的 INSTALL 檔案中的說明建立特殊 Perl 時才能使用。

例如,每當你從套件 DB 呼叫 Perl 內建的 caller 函數時,對應堆疊架構所呼叫的自變數會複製到 @DB::args 陣列。這些機制可透過使用 -d 開關呼叫 Perl 來啟用。特別是,會啟用下列其他功能(請參閱 "$^P" in perlvar

請注意,如果 &DB::sub 需要外部資料才能運作,則在沒有資料的情況下無法呼叫子常式。例如,標準除錯器的 &DB::sub 取決於 $DB::deep 變數(它定義了在強制中斷之前,您可以在除錯器中深入遞迴的層級數)。如果未定義 $DB::deep,則無法呼叫子常式,即使 &DB::sub 存在。

撰寫您自己的除錯器

環境變數

PERL5DB 環境變數可用於定義除錯器。例如,最小的「工作中」除錯器(實際上它什麼都不做)包含一行

sub DB::DB {}

可以輕鬆地這樣定義

$ PERL5DB="sub DB::DB {}" perl -d your-script

另一個簡短的除錯器,稍有用途,可以用以下一行建立

sub DB::DB {print ++$i; scalar <STDIN>}

此除錯器會列印一個數字,該數字會隨著遇到的每個陳述式而遞增,並在繼續執行下一個陳述式之前等待您按一下換行符號。

以下除錯器實際上很有用

{
  package DB;
  sub DB  {}
  sub sub {print ++$i, " $sub\n"; &$sub}
}

它會列印每個子常式呼叫的順序號碼和所呼叫子常式的名稱。請注意,&DB::sub 透過使用 package 指令編譯到套件 DB 中。

當它啟動時,除錯程式會讀取您的 rc 檔案(Unix 下的 ./.perldb~/.perldb),它可以設定重要的選項。(也可以在這裡定義一個子常式 (&afterinit);它會在除錯程式完成自己的初始化後執行。)

在讀取 rc 檔案後,除錯程式會讀取 PERLDB_OPTS 環境變數,並用它來設定除錯程式選項。這個變數的內容會被視為除錯程式命令 o ... 的引數(請參閱 perldebug 中的「可設定選項」)。

除錯程式內部變數

除了上面提到的檔案和子常式相關變數外,除錯程式還會維護各種神奇的內部變數。

除錯程式自訂函式

提供了一些函式來簡化自訂。

請注意,此手冊頁面(或 perldebug)中未記載的任何變數和函式都只供內部使用,因此可能會在未經通知的情況下變更。

框架清單輸出範例

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 選項 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 值的範例,讓您了解設定之間的差異。儘管很長,但這不是完整的清單,而只是摘錄。

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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: ''

在上述所有情況中,行縮排顯示呼叫樹狀結構。如果設定了 frame 的第 2 個位元,則在退出子常式時也會列印一行。如果設定了第 4 個位元,則會列印引數以及呼叫方資訊。如果設定了第 8 個位元,則即使引數是繫結或參考,也會列印引數。如果設定了第 16 個位元,則也會列印回傳值。

當編譯套件時,會列印類似下列的程式碼行,並適當地縮排。

Package lib/Carp.pm.

is printed with proper indentation.

偵錯正規表示式

有兩種方法可以啟用正規表示式的偵錯輸出。

如果您的 perl 是使用 -DDEBUGGING 編譯的,則可以在命令列上使用 -Dr 旗標,並使用 -Drv 進行更詳細的資訊。

否則,可以使用 re 'debug',它在編譯時和執行時都會產生效果。從 Perl 5.9.5 開始,此實用程式會以詞彙範圍為範圍。

編譯時輸出

編譯時的偵錯輸出如下所示

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+size*8 的偏移量/長度表的總位元組數。下一行顯示執行配對的第一個節點的標籤 id

The

anchored 'de' at 1 floating 'gh' at 3..2147483647 (checking floating) 
      stclass 'ANYOF[bc]' minlen 7 

行(分成上面兩行)包含最佳化資訊。在顯示的範例中,最佳化器發現配對應包含在偏移量 1 的子字串 de,加上在 3 到無限大之間某個偏移量的子字串 gh。此外,在檢查這些子字串(以快速放棄不可能的配對)時,Perl 會在檢查子字串 de 之前檢查子字串 gh。最佳化器也可能使用配對從字元類別(在 first id)開始,而且沒有任何短於 7 個字元的字串可能配對的知識。

可能出現在此行中的感興趣欄位為

anchored STRING at POS
floating STRING at POS1..POS2

請參閱上方。

matching floating/anchored

要先檢查哪個子字串。

minlen

配對的最小長度。

stclass TYPE

第一個配對節點的類型。

noscan

不要掃描已找到的子字串。

isall

表示最佳化器資訊就是正規表示式包含的所有內容,因此根本不需要進入正規表示式引擎。

GPOS

設定如果樣式包含 \G

plus

設定如果樣式以重複字元開頭(如 x+y)。

implicit

設定如果樣式以 .* 開頭。

with eval

設定如果樣式包含 eval 群組,例如 (?{ code })(??{ code })

anchored(TYPE)

如果樣式可能僅在少數位置配對,其中 TYPESBOLMBOLGPOS。請參閱下表。

如果已知子字串僅在行尾配對,則可以在其後加上 $,例如 floating 'k'$

最佳化器特定資訊用於避免在無法明確配對的字串上輸入(緩慢的)正規表示法引擎。如果設定 isall 旗標,則即使最佳化器找到適當的配對位置,也可以避免呼叫正規表示法引擎。

在最佳化器區段上方是正規表示法編譯形式的 節點 清單。每行格式為

id: TYPE OPTIONAL-INFO (next-id)

節點類型

以下是目前可能的類型,附有簡短說明

# TYPE arg-description [regnode-struct-suffix] [longjump-len] DESCRIPTION

# Exit points

END              no         End of program.
SUCCEED          no         Return from a subroutine, basically.

# Line Start Anchors:
SBOL             no         Match "" at beginning of line: /^/, /\A/
MBOL             no         Same, assuming multiline: /^/m

# Line End Anchors:
SEOL             no         Match "" at end of line: /$/
MEOL             no         Same, assuming multiline: /$/m
EOS              no         Match "" at end of string: /\z/

# Match Start Anchors:
GPOS             no         Matches where last m//g left off.

# Word Boundary Opcodes:
BOUND            no         Like BOUNDA for non-utf8, otherwise like
                            BOUNDU
BOUNDL           no         Like BOUND/BOUNDU, but \w and \W are
                            defined by current locale
BOUNDU           no         Match "" at any boundary of a given type
                            using /u rules.
BOUNDA           no         Match "" at any boundary between \w\W or
                            \W\w, where \w is [_a-zA-Z0-9]
NBOUND           no         Like NBOUNDA for non-utf8, otherwise like
                            BOUNDU
NBOUNDL          no         Like NBOUND/NBOUNDU, but \w and \W are
                            defined by current locale
NBOUNDU          no         Match "" at any non-boundary of a given
                            type using using /u rules.
NBOUNDA          no         Match "" betweeen any \w\w or \W\W, where
                            \w is [_a-zA-Z0-9]

# [Special] alternatives:
REG_ANY          no         Match any one character (except newline).
SANY             no         Match any one character.
ANYOF            sv         Match character in (or not in) this class,
                 charclass  single char match only
ANYOFD           sv         Like ANYOF, but /d is in effect
                 charclass
ANYOFL           sv         Like ANYOF, but /l is in effect
                 charclass
ANYOFPOSIXL      sv         Like ANYOFL, but matches [[:posix:]]
                 charclass_ classes
                 posixl

ANYOFH           sv 1       Like ANYOF, but only has "High" matches,
                            none in the bitmap; the flags field
                            contains the lowest matchable UTF-8 start
                            byte
ANYOFHb          sv 1       Like ANYOFH, but all matches share the same
                            UTF-8 start byte, given in the flags field
ANYOFHr          sv 1       Like ANYOFH, but the flags field contains
                            packed bounds for all matchable UTF-8 start
                            bytes.
ANYOFHs          sv:str 1   Like ANYOFHb, but has a string field that
                            gives the leading matchable UTF-8 bytes;
                            flags field is len
ANYOFR           packed 1   Matches any character in the range given by
                            its packed args: upper 12 bits is the max
                            delta from the base lower 20; the flags
                            field contains the lowest matchable UTF-8
                            start byte
ANYOFRb          packed 1   Like ANYOFR, but all matches share the same
                            UTF-8 start byte, given in the flags field

ANYOFHbbm        none bbm   Like ANYOFHb, but only for 2-byte UTF-8
                            characters; uses a bitmap to match the
                            continuation byte

ANYOFM           byte 1     Like ANYOF, but matches an invariant byte
                            as determined by the mask and arg
NANYOFM          byte 1     complement of ANYOFM

# POSIX Character Classes:
POSIXD           none       Some [[:class:]] under /d; the FLAGS field
                            gives which one
POSIXL           none       Some [[:class:]] under /l; the FLAGS field
                            gives which one
POSIXU           none       Some [[:class:]] under /u; the FLAGS field
                            gives which one
POSIXA           none       Some [[:class:]] under /a; the FLAGS field
                            gives which one
NPOSIXD          none       complement of POSIXD, [[:^class:]]
NPOSIXL          none       complement of POSIXL, [[:^class:]]
NPOSIXU          none       complement of POSIXU, [[:^class:]]
NPOSIXA          none       complement of POSIXA, [[:^class:]]

CLUMP            no         Match any extended grapheme cluster
                            sequence

# Alternation

# BRANCH        The set of branches constituting a single choice are
#               hooked together with their "next" pointers, since
#               precedence prevents anything being concatenated to
#               any individual branch.  The "next" pointer of the last
#               BRANCH in a choice points to the thing following the
#               whole choice.  This is also where the final "next"
#               pointer of each individual branch points; each branch
#               starts with the operand node of a BRANCH node.
#
BRANCH           node 1     Match this alternative, or the next...

# Literals

EXACT            str        Match this string (flags field is the
                            length).

# In a long string node, the U32 argument is the length, and is
# immediately followed by the string.
LEXACT           len:str 1  Match this long string (preceded by length;
                            flags unused).
EXACTL           str        Like EXACT, but /l is in effect (used so
                            locale-related warnings can be checked for)
EXACTF           str        Like EXACT, but match using /id rules;
                            (string not UTF-8, ASCII folded; non-ASCII
                            not)
EXACTFL          str        Like EXACT, but match using /il rules;
                            (string not likely to be folded)
EXACTFU          str        Like EXACT, but match using /iu rules;
                            (string folded)

EXACTFAA         str        Like EXACT, but match using /iaa rules;
                            (string folded except MICRO in non-UTF8
                            patterns; doesn't contain SHARP S unless
                            UTF-8; folded length <= unfolded)
EXACTFAA_NO_TRIE str        Like EXACTFAA, (string not UTF-8, folded
                            except: MICRO, SHARP S; folded length <=
                            unfolded, not currently trie-able)

EXACTFUP         str        Like EXACT, but match using /iu rules;
                            (string not UTF-8, folded except MICRO:
                            hence Problematic)

EXACTFLU8        str        Like EXACTFU, but use /il, UTF-8, (string
                            is folded, and everything in it is above
                            255
EXACT_REQ8       str        Like EXACT, but only UTF-8 encoded targets
                            can match
LEXACT_REQ8      len:str 1  Like LEXACT, but only UTF-8 encoded targets
                            can match
EXACTFU_REQ8     str        Like EXACTFU, but only UTF-8 encoded
                            targets can match

EXACTFU_S_EDGE   str        /di rules, but nothing in it precludes /ui,
                            except begins and/or ends with [Ss];
                            (string not UTF-8; compile-time only)

# New charclass like patterns
LNBREAK          none       generic newline pattern

# Trie Related

# Behave the same as A|LIST|OF|WORDS would. The '..C' variants
# have inline charclass data (ascii only), the 'C' store it in the
# structure.

TRIE             trie 1     Match many EXACT(F[ALU]?)? at once.
                            flags==type
TRIEC            trie       Same as TRIE, but with embedded charclass
                 charclass  data

AHOCORASICK      trie 1     Aho Corasick stclass. flags==type
AHOCORASICKC     trie       Same as AHOCORASICK, but with embedded
                 charclass  charclass data

# Do nothing types

NOTHING          no         Match empty string.
# A variant of above which delimits a group, thus stops optimizations
TAIL             no         Match empty string. Can jump here from
                            outside.

# Loops

# STAR,PLUS    '?', and complex '*' and '+', are implemented as
#               circular BRANCH structures.  Simple cases
#               (one character per match) are implemented with STAR
#               and PLUS for speed and to minimize recursive plunges.
#
STAR             node       Match this (simple) thing 0 or more times:
                            /A{0,}B/ where A is width 1 char
PLUS             node       Match this (simple) thing 1 or more times:
                            /A{1,}B/ where A is width 1 char

CURLY            sv 3       Match this (simple) thing {n,m} times:
                            /A{m,n}B/ where A is width 1 char
CURLYN           no 3       Capture next-after-this simple thing:
                            /(A){m,n}B/ where A is width 1 char
CURLYM           no 3       Capture this medium-complex thing {n,m}
                            times: /(A){m,n}B/ where A is fixed-length
CURLYX           sv 3       Match/Capture this complex thing {n,m}
                            times.

# This terminator creates a loop structure for CURLYX
WHILEM           no         Do curly processing and see if rest
                            matches.

# Buffer related

# OPEN,CLOSE,GROUPP     ...are numbered at compile time.
OPEN             num 1      Mark this point in input as start of #n.
CLOSE            num 1      Close corresponding OPEN of #n.
SROPEN           none       Same as OPEN, but for script run
SRCLOSE          none       Close preceding SROPEN

REF              num 2      Match some already matched string
REFF             num 2      Match already matched string, using /di
                            rules.
REFFL            num 2      Match already matched string, using /li
                            rules.
REFFU            num 2      Match already matched string, usng /ui.
REFFA            num 2      Match already matched string, using /aai
                            rules.

# Named references.  Code in regcomp.c assumes that these all are after
# the numbered references
REFN             no-sv 2    Match some already matched string
REFFN            no-sv 2    Match already matched string, using /di
                            rules.
REFFLN           no-sv 2    Match already matched string, using /li
                            rules.
REFFUN           num 2      Match already matched string, using /ui
                            rules.
REFFAN           num 2      Match already matched string, using /aai
                            rules.

# Support for long RE
LONGJMP          off 1 1    Jump far away.
BRANCHJ          off 2 1    BRANCH with long offset.

# Special Case Regops
IFMATCH          off 1 1    Succeeds if the following matches; non-zero
                            flags "f", next_off "o" means lookbehind
                            assertion starting "f..(f-o)" characters
                            before current
UNLESSM          off 1 1    Fails if the following matches; non-zero
                            flags "f", next_off "o" means lookbehind
                            assertion starting "f..(f-o)" characters
                            before current
SUSPEND          off 1 1    "Independent" sub-RE.
IFTHEN           off 1 1    Switch, should be preceded by switcher.
GROUPP           num 1      Whether the group matched.

# The heavy worker

EVAL             evl/flags  Execute some Perl code.
                 2

# Modifiers

MINMOD           no         Next operator is not greedy.
LOGICAL          no         Next opcode should set the flag only.

# This is not used yet
RENUM            off 1 1    Group with independently numbered parens.

# Regex Subroutines
GOSUB            num/ofs 2  recurse to paren arg1 at (signed) ofs arg2

# Special conditionals
GROUPPN          no-sv 1    Whether the group matched.
INSUBP           num 1      Whether we are in a specific recurse.
DEFINEP          none 1     Never execute directly.

# Backtracking Verbs
ENDLIKE          none       Used only for the type field of verbs
OPFAIL           no-sv 1    Same as (?!), but with verb arg
ACCEPT           no-sv/num  Accepts the current matched string, with
                 2          verbar

# Verbs With Arguments
VERB             no-sv 1    Used only for the type field of 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

# Control what to keep in $&.
KEEPS            no         $& begins here.

# Validate that lookbehind IFMATCH and UNLESSM end at the right place
LOOKBEHIND_END   no         Return from lookbehind (IFMATCH/UNLESSM)
                            and validate position

# SPECIAL  REGOPS

# This is not really a node, but an optimized away piece of a "long"
# node.  To simplify debugging output, we mark it as if it were a node
OPTIMIZED        off        Placeholder for dump.

# Special opcode with the property that no opcode in a compiled program
# will ever be of this type. Thus it can be used as a flag value that
# no other opcode has been seen. END is used similarly, in that an END
# node cant be optimized. So END implies "unoptimizable" and PSEUDO
# mean "not seen anything to optimize yet".
PSEUDO           off        Pseudo opcode for internal use.

REGEX_SET        depth p    Regex set, temporary node used in pre-
                            optimization compilation

在最佳化器資訊之後,是偏移量/長度表的轉儲,這裡分為多行

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 個項目。每個項目都是一對整數,表示為 offset[length]。項目編號從 1 開始,因此此處的項目 #1 為 1[4],項目 #12 為 5[1]1[4] 表示標籤為 1: 的節點(1: ANYOF[bc])在正規表示式的預編譯形式中從字元位置 1 開始,長度為 4 個字元。位置 12 中的 5[1] 表示標籤為 12: 的節點(12: EXACT <d>)在正規表示式的預編譯形式中從字元位置 5 開始,長度為 1 個字元。位置 14 中的 12[1] 表示標籤為 14: 的節點(14: CURLYX[0] {1,32767})在正規表示式的預編譯形式中從字元位置 12 開始,長度為 1 個字元---也就是說,它對應於預編譯正規表示式中的 + 符號。

0[0] 項目表示沒有對應的節點。

執行時期輸出

首先,執行比對時,即使已啟用偵錯,也可能沒有執行時期輸出。這表示從未進入正規表示式引擎,因此所有工作都由最佳化器完成。

如果已進入正規表示式引擎,輸出可能會如下所示

  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...

輸出中最重要的資訊是關於目前針對目標字串測試的編譯正規表示式特定節點。這些行的格式為

字串偏移量 <字串前> <字串後> |ID: 類型

TYPE 資訊會根據回溯層級縮排。其他附帶資訊會穿插顯示在其中。

除錯 Perl 記憶體使用量

Perl 在使用記憶體時很浪費。有句諺語說,要估計 Perl 的記憶體使用量,假設一個合理的記憶體配置演算法,將估計值乘以 10,即使這樣還是可能估計錯誤,但至少不會太驚訝。這句話並非完全正確,但可以很好地掌握發生了什麼事。

假設一個整數不能少於 20 個位元組的記憶體,一個浮點數不能少於 24 個位元組,一個字串不能少於 32 個位元組(所有這些範例都假設是 32 位元架構,在 64 位元架構中結果會更糟)。如果一個變數以三種不同方式中的兩種方式存取(需要一個整數、一個浮點數或一個字串),記憶體使用量可能會再增加 20 個位元組。一個隨便的 malloc(3) 實作會大幅增加這些數字。

在範圍的另一端,像這樣的宣告

sub foo;

可能會佔用多達 500 個位元組的記憶體,具體取決於您執行的 Perl 版本。

來源到編譯程式碼膨脹的軼事估計表明會增加八倍。這表示合理的(通常有註解、正確縮排等)程式碼的編譯形式將佔用比程式碼在磁碟上佔用的空間大約多八倍的記憶體。

自 Perl 5.6.0 以來,-DL 命令列開關已過時(僅當 Perl 使用 -DDEBUGGING 建置時才可用)。此開關用於追蹤 Perl 的記憶體配置和可能的記憶體外洩。現在建議改用 malloc 除錯工具,例如 Purifyvalgrind。另請參閱 perlhacktips 中的「PERL_MEM_LOG」

找出 Perl 資料結構使用多少記憶體的一種方法是從 CPAN 安裝 Devel::Size 模組:它會提供儲存特定資料結構所需的最小位元組數。請注意 size() 和 total_size() 之間的差異。

如果 Perl 已使用 Perl 的 malloc 編譯,您可以透過設定 $ENV{PERL_DEBUG_MSTATS} 來分析 Perl 記憶體使用情況。

使用 $ENV{PERL_DEBUG_MSTATS}

如果您的 perl 使用 Perl 的 malloc(),且已使用必要的開關編譯(這是預設值),則在編譯您的程式碼後,當 $ENV{PERL_DEBUG_MSTATS} > 1 時,它會列印記憶體使用情況統計資料;在程式終止前,當 $ENV{PERL_DEBUG_MSTATS} >= 1 時,它也會列印統計資料。報告格式類似於以下範例

 $ PERL_DEBUG_MSTATS=2 perl -e "require Carp"
 Memory allocation statistics after compilation: (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.
 Memory allocation statistics after execution:   (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.

您可以使用標準 Devel::Peek 模組中的 mstat() 函數,在執行中的任意點要求此類統計資料。

以下是該格式的一些說明

區塊 SMALLEST(APPROX)..GREATEST(APPROX)

Perl 的 malloc() 使用區塊分配。每個要求都會向上取整至最接近的可用區塊大小,並從該大小的區塊池中取出一個區塊。

上述行描述目前使用中區塊的限制。每個區塊有兩種大小:記憶體使用量和可放入此區塊的使用者資料最大大小。假設在上述範例中,最小區塊大小為 4。最大區塊的可使用大小為 8188,記憶體使用量為 8192。

在為偵錯而建置的 Perl 中,有些區塊可能具有負的可使用大小。這表示這些區塊無法(也不會)被使用。對於較大的區塊,記憶體使用量可能比 2 的次方大一頁。如果是這樣,上述 APPROX 欄位中會列印對應的 2 的次方。

已釋放/已使用

隨後的一或兩列數字對應於 SMALLESTGREATEST 之間每個大小的區塊數。在第一列中,區塊的大小(記憶體使用量)是 2 的次方,或可能大一頁。在第二列中(如果存在),區塊的記憶體使用量介於「上方」兩個區塊的記憶體使用量之間。

例如,假設在先前的範例中,記憶體使用量為

   free:    8     16    32    64    128  256 512 1024 2048 4096 8192
	   4     12    24    48    80

使用非DEBUGGING perl 時,從128 開始的儲存區有 4 位元組的額外負擔,因此長度為 8192 的儲存區可能需要多達 8188 位元組的配置。

Total sbrk(): SBRKed/SBRKs:CONTINUOUS

前兩個欄位提供 perl sbrk(2)ed (ess-broken? :-) 的總記憶體量和使用的 sbrk(2) 數量。第三個數字是 perl 認為的傳回區塊的連續性。只要這個數字為正,malloc() 就會假設 sbrk(2) 可能會提供連續記憶體。

外部函式庫配置的記憶體不會計算在內。

pad: 0

保持儲存區對齊所需的 sbrk(2)ed 記憶體量。

heads: 2192

雖然較大儲存區的記憶體額外負擔會保留在儲存區內,但對於較小的儲存區,則會保留在個別區域中。此欄位提供這些區域的總大小。

chain: 0

malloc() 可能會想要將較大的儲存區細分為較小的儲存區。如果已故儲存區中只有一部分未細分,其餘部分將保留為連結清單的元素。此欄位提供這些區塊的總大小。

tail: 6144

為了將 sbrk(2) 的數量降至最低,malloc() 會要求更多的記憶體。此欄位提供尚未使用的部分的大小,此部分已 sbrk(2)ed,但從未觸及。

另請參閱

perldebugperl5db.plperlgutsperlrunreDevel::DProf