目錄

名稱

perldebug - Perl 調試

描述

首先,您試過使用use strict;use warnings;了嗎?

如果您是Perl調試器的新手,您可能更喜歡閱讀perldebtut,這是對調試器的教程介紹。

如果您正在尋找調試器的實現細節,您可能更喜歡閱讀perldebguts

對於深入的技術使用細節,請參閱perl5db.pl,即調試器本身的文檔。

Perl 調試器

如果您使用 -d 開關來調用 Perl,則您的腳本將在 Perl 源代碼調試器下運行。這類似於交互式 Perl 環境,提示調試器命令,讓您檢查源代碼、設置斷點、獲取堆棧回溯、更改變量的值等。這非常方便,以至於您經常會單獨啟動調試器,僅僅是為了交互地測試 Perl 結構以查看其功能。例如

$ perl -d -e 42

在 Perl 中,調試器不是像在典型的編譯環境中那樣是一個獨立的程序。相反,-d 標誌告訴編譯器將源信息插入到它即將交給解釋器的解析樹中。這意味著您的代碼必須首先編譯正確,調試器才能對其起作用。然後,當解釋器啟動時,它會預先加載一個包含調試器的特殊 Perl 庫文件。

該程序將在執行第一個運行時可執行的語句之前停止(但請參閱下文有關編譯時語句的部分),並要求您輸入調試器命令。與常見預期相反,每當調試器停止並顯示一行代碼時,它總是顯示它即將執行的代碼行,而不是它剛剛執行的代碼行。

調試器未識別的任何命令都將直接在當前包中作為 Perl 代碼執行(使用 DB 包來保存其自身的狀態信息)。

請注意,所述的 eval 受到隱式範圍的限制。因此,在 eval 之後,任何新引入的語言變量或任何修改的捕獲緩衝區內容都將丟失。調試器是學習 Perl 的一個不錯的環境,但是如果您使用應該在同一範圍內的材料進行交互式實驗,請將其放在一行中。

對於在調試器提示中輸入的任何文本,在進一步處理之前,將首尾的空白先去除。如果調試器命令與您自己程序中的某些函數相符,只需在函數之前加上一些看起來不像是調試器命令的東西,例如一個前導的 ; 或者可能是一個 +,或者用括號或大括號括起來。

調用除錯器

有幾種方法可以調用除錯器

perl -d 程式名稱

對指定的程式使用 程式名稱

perl -d -e 0

使用 -e 以互動方式提供任意的 表達式

perl -d:ptkdb 程式名稱

透過 Devel::ptkdb 圖形使用者介面 (GUI) 來除錯指定的程式。

perl -dt 多線程程式名稱

使用線程來除錯指定的程式(實驗性功能)。

如果使用 -d 選項來呼叫 Perl,變數 $^P 將保持真值。這在需要知道程式是否在除錯器下運行時非常有用。

if ( $^P ) {
    # running under the debugger
}

詳細資訊請參閱 perlvar 中的 "$^P"

除錯器指令

互動式除錯器了解以下指令

h

列印出摘要說明訊息

h [指令]

為給定的除錯器指令列印出說明訊息。

h h

h h 的特殊參數會產生整個說明頁面,這相當長。

如果 h h 指令的輸出(或者任何指令)超出了您的屏幕,請在指令前加上前導管道符號,使其通過分頁器運行,如下所示

DB> |h h

您可以通過 o pager=... 指令來更改所使用的分頁器。

p 表達式

與當前套件中的 print {$DB::OUT} expr 相同。特別是,因為這只是 Perl 自己的 print 函數,這意味著嵌套的資料結構和物件不會被轉儲,不像 x 指令。

DB::OUT 文件處理程序被打開到 /dev/tty,不管 STDOUT 可能被重定向到何處。

x [最大深度] 表達式

以列表上下文評估其表達式並以漂亮的方式輸出結果。嵌套的資料結構會被遞歸地打印出來,不像 Perl 中的真正的 print 函數。當輸出哈希時,您可能更喜歡使用 'x \%h' 而不是 'x %h'。如果您想自己這樣做,請參閱 Dumpvalue

輸出格式由描述在 "可配置選項" 下的多個選項所控制。

如果包含了 maxdepth,它必須是一個數字 N;值只會被打印出 N 層深,就像暫時將 dumpDepth 選項設置為 N 一樣。

V [pkg [vars]]

顯示包(默認為 main)中的所有(或部分)變數,使用一個數據漂亮的打印機(哈希顯示它們的鍵和值,以便您知道是什麼,控制字符被製作為可打印字符,等等)。確保不要放入類型指定符(如 $),只是符號名稱,像這樣

V DB filename line

使用 ~pattern!pattern 進行正和負的正則表達式匹配。

這類似於對每個適用的變量調用 x 命令。

X [vars]

V currentpackage [vars] 相同。

y [level [vars]]

顯示當前作用域或 level 作用域更高的所有(或部分)區域變數(記憶單元: mY 變數)。您可以使用 vars 來限制您看到的變量,其工作方式與 VX 命令完全相同。需要 PadWalker 模塊版本 0.08 或更高版本;如果沒有安裝,將會警告。輸出的格式與 V 的格式相同,並且格式由相同的選項控制。

T

生成一個堆棧回溯。有關其輸出的詳細信息,請參閱下面。

s [expr]

單步執行。執行到另一條語句的開始,進入子例程調用。如果提供了包含函數調用的表達式,它也將進行單步執行。

n [expr]

下一步。執行到下一條語句的開始,跳過子例程調用。如果提供了包含函數調用的表達式,將在每條語句之前停止該函數的執行。

r

繼續直到從當前子程序返回。如果設置了PrintRet選項(默認),則丟棄返回值。

<CR>

重複上一個ns命令。

c [行號|子程序]

繼續執行,可選地在指定行或子程序處插入一次性斷點。

l

列出下一窗口的行。

l 最小值+增量

列出從min開始的incr+1行。

l 最小值-最大值

列出minmax之間的行。l --是同義詞。

l 行號

列出單行。

l 子程序名稱

列出子程序的第一窗口的行。 subname 可能是包含代碼引用的變量。

-

列出上一窗口的行。

v [行號]

查看當前行周圍的幾行代碼。

.

將內部調試器指針返回到最後執行的行,並打印出該行。

f 文件名

切換到查看不同的文件或eval語句。如果filename不是在%INC的值中找到的完整路徑名,則將其視為正則表達式。

eval的字符串(如果可訪問)被視為文件名:f (eval 7)f eval 7\b訪問第7個eval字符串的主體(按照執行順序)。當前執行的eval和定義子程序的eval字符串的主體被保存,因此可訪問。

/pattern/

向前搜索模式(Perl正則表達式);最後的/可選。默認情況下,搜索是不區分大小寫的。

?pattern?

向後搜索模式;最後的?可選。默認情況下,搜索是不區分大小寫的。

L [abw]

列出(默認全部)動作、斷點和監視表達式

S [[!]regex]

列出與正則表達式匹配的子程序名稱 [不]。

t [n]

切換追蹤模式(另請參閱 AutoTrace 選項)。可選參數為追蹤當前層級以下的最大層級數;超過該層級的任何事物將不會輸出。

t [n] expr

追蹤執行 expr。可選的第一個參數為追蹤當前層級以下的最大層級數;超過該層級的任何事物將不會輸出。請參閱 "perldebguts 中的框架列表輸出示例" 以查看示例。

b

在當前行設置斷點。

b [line] [condition]

在指定行之前設置斷點。如果指定了條件,則每次達到該語句時將評估該條件:僅在條件為 true 時才會觸發斷點。斷點僅能設置在開始可執行語句的行上。條件不使用 if

b 237 $x > 30
b 237 ++$count237 < 11
b 33 /pattern/i

如果行號是 .,則在當前行設置斷點。

b . $n > 100
b [file]:[line] [condition]

在(可能是不同的)文件中指定行之前設置斷點。如果指定了條件,則每次達到該語句時將評估該條件:僅在條件為 true 時才會觸發斷點。斷點僅能設置在開始可執行語句的行上。條件不使用 if

b lib/MyModule.pm:237 $x > 30
b /usr/lib/perl5/site_perl/CGI.pm:100 ++$count100 < 11
b subname [condition]

在命名的子例程的第一行之前設置斷點。 subname 可能是包含代碼引用的變量(在這種情況下,不支持 condition)。

b postpone subname [condition]

在編譯後的子例程的第一行設置斷點。

b load filename

filename 的第一個執行行之前設置斷點,該文件應該是在 %INC 值中找到的完整路徑名之一。

b compile subname

在指定子例程編譯後執行的第一個語句之前設置斷點。

B line

從指定的 line 中刪除斷點。

B *

刪除所有已安裝的斷點。

disable [file]:[line]

禁用斷點,以防止其停止程序的執行。 斷點默認情況下是啟用的,可以使用 enable 命令重新啟用斷點。

disable [line]

禁用斷點,以防止其停止程序的執行。 斷點默認情況下是啟用的,可以使用 enable 命令重新啟用斷點。

這是針對當前文件中的斷點而完成的。

啟用 [檔案]:[行號]

啟用中斷點,使其停止程式的執行。

啟用 [行號]

啟用中斷點,使其停止程式的執行。

這是針對當前文件中的斷點而完成的。

a [行號] 命令

在執行該行之前設置要執行的動作。如果省略了 行號,則在即將執行的行上設置動作。調試器執行的步驟順序如下:

1. check for a breakpoint at this line
2. print the line if necessary (tracing)
3. do any actions associated with that line
4. prompt user if at a breakpoint or in single-step
5. evaluate line

例如,每次通過第 53 行時,這將會輸出 $foo

a 53 print "DB FOUND $foo\n"
A 行

從指定行中刪除動作。

A *

刪除所有已安裝的動作。

w expr

添加全局監視表達式。每當監視的全局變量更改時,調試器將停止並顯示舊值和新值。

W expr

刪除監視表達式

W *

刪除所有監視表達式。

o

顯示所有選項。

o booloption ...

將列出的每個布爾選項設置為值 1

o anyoption? ...

打印出一個或多個選項的值。

o option=value ...

設置一個或多個選項的值。如果值中有內部空白,則應該加引號。例如,您可以設置 o pager="less -MQeicsNfr" 來調用具有這些特定選項的 less。您可以使用單引號或雙引號,但如果這樣做,您必須逃脫任何嵌入的相同類型的引號實例,以及逃脫任何立即位於該引號之前的逃脫,但不意味著逃脫引號本身的逃脫。換句話說,您遵循單引號規則,而不論引號;例如:o option='this isn\'t bad'o option="She said, \"Isn't it?\""

出於歷史原因,=value 是可選的,但默認值為 1,只有在安全的情況下才會這樣--主要是布爾選項。最好始終使用 = 分配特定值。選項可以縮寫,但為了清晰起見,可能不應該這樣做。可以一次設置多個選項。參見 "可配置選項" 查看這些選項的列表。

< ?

列出所有預提示 Perl 命令操作。

< [ command ]

在每次調試器提示之前設置一個動作(Perl 命令)。可以通過反斜杠新行輸入多行命令。

< *

刪除所有預提示 Perl 命令操作。

<< command

在每次調試器提示之前添加一個動作(Perl 命令)。可以通過反斜杠新行輸入多行命令。

> ?

列出所有後提示 Perl 命令操作。

> command

在您剛剛給出命令返回執行腳本時的提示之後設置一個動作(Perl 命令)。可以通過反斜杠新行(我們打賭您現在可能無法猜到)輸入多行命令。

> *

刪除所有後提示 Perl 命令操作。

>> command

在您剛剛給出命令返回執行腳本時的提示之後添加一個動作(Perl 命令)。可以通過反斜杠新行輸入多行命令。

{ ?

列出所有預提示調試器命令。

{ [ command ]

在每次調試器提示之前設置一個動作(調試器命令)。可以按照慣例輸入多行命令。

由於這個命令在某些意義上是新的,如果您看起來意外地輸入了一個塊,將會發出警告。如果那就是您的意思,請按照 ;{ ... } 或甚至 do { ... } 的方式書寫。

{ *

刪除所有預提示調試器命令。

{{ command

在每次調試器提示之前添加一個動作(調試器命令)。如果您能猜到如何輸入多行命令,則可以這樣做:參見上文。

! number

重做以前的命令(默認為上一個命令)。

! -number

重做第 number 個以前的命令。

! pattern

重做以 pattern 開頭的最後一個命令。另請參閱 o recallCommand

!! cmd

在子進程中運行 cmd(從 DB::IN 讀取,寫入 DB::OUT)。另請參閱 o shellBang。請注意,將使用用戶當前的 shell(好吧,他們的 $ENV{SHELL} 變量),這可能會干擾對退出狀態或信號和核心轉儲信息的正確解釋。

source file

file 中讀取並執行調試器命令。 file 本身可能包含 source 命令。

H -number

顯示最後 n 個指令。僅列出長度超過一個字元的指令。若省略 number,則列出所有指令。

q 或 ^D

退出。("quit"對於此無效,除非您已建立了別名) 這是退出調試器的唯一支持方法,但連續輸入 exit 或許也能夠工作。

如果您希望能夠跨過腳本末端進行單步執行,請將 inhibit_exit 選項設置為 0。如果您希望在全局析構過程中進行單步執行,您可能還需要將 $finished 設置為 0。

R

通過 exec() 啟動一個新的會話來重新啟動調試器。我們會嘗試在此過程中保留您的歷史記錄,但內部設置和命令行選項可能會丟失。

目前保留的設置包括:歷史記錄、斷點、動作、調試器選項以及 Perl 命令行選項 -w-I-e

|dbcmd

執行調試器命令,將 DB::OUT 輸出到您當前的分頁器。

||dbcmd

|dbcmd 相同,但同時暫時將 DB::OUT 選為 select

= [alias value]

定義命令別名,如

= quit q

或列出當前別名。

command

將命令作為 Perl 陳述執行。將提供尾隨分號。如果 Perl 陳述否則會被誤認為 Perl 調試器,則也可以使用前置分號。

m expr

列出可以在評估表達式結果上調用的方法。表達式可以評估為對象的參考,也可以評估為包名。

M

顯示所有已加載的模塊及其版本。

man [manpage]

儘管其名稱如此,這將調用您系統的默認文檔查看器查看給定頁面,或者在省略 manpage 時查看查看器本身。如果該查看器是 man,則使用當前的 Config 信息來調用 man,使用正確的 MANPATH 或 -M manpath 選項。對於形式為 XXX 的已知 man 頁面,如果匹配已知的形式為 perlXXX 的 man 頁面,則會重新嘗試。這讓您可以在調試器中輸入 man debugman op

在傳統上缺乏可用的 man 命令的系統上,調試器將調用 perldoc。偶爾,由於固執的供應商或者更為幸運的用戶,這一確定是不正確的。如果您屬於任一類別,只需手動設置 $DB::doccmd 變量以查看您系統上的 Perl 文檔。這可以在一個 rc 文件中設置,也可以通過直接賦值進行設置。我們仍在等待類似以下內容的可用示例:

$DB::doccmd = 'netscape -remote http://something.here/';

可配置選項

調試器有許多選項可使用 o 命令來設置,可以是互動式的,也可以來自環境或 rc 檔案。該檔案在 Unix 下命名為 ./.perldb~/.perldb,在其他情況下為 perldb.ini

recallCommand, ShellBang

用於召回命令或生成 shell 的字符。默認情況下,兩者都設置為 !,這是不幸的。

pager

用於 pager 管道命令(以 | 字符開頭的命令)的輸出程序。默認情況下,將使用 $ENV{PAGER}。因為調試器使用您當前的終端特性來進行粗體和下劃線,如果所選的 pager 不保持逃逸序列不變,則通過 pager 發送的某些調試器命令的輸出將無法讀取。

tkRunning

在提示時運行 Tk(使用 ReadLine)。

signalLevel, warnLevel, dieLevel

冗長程度。默認情況下,調試器會保持您的異常和警告不變,因為修改它們可能會破壞正確運行的程序。當未捕獲的 INT、BUS 或 SEGV 信號到達時,它將嘗試打印消息。(但請參見下面的 "BUGS" 中關於信號的提及。)

要禁用此默認的安全模式,將這些值設置為高於 0 的值。在等級為 1 時,收到任何類型的警告時都會得到回溯(這通常很煩人),或者收到異常時(這通常很有價值)。不幸的是,調試器無法分辨致命異常和非致命異常。如果 dieLevel 甚至為 1,則您的非致命異常也將被追蹤並且毫不客氣地更改,如果它們來自於 eval'ed 字符串或者來自您嘗試加載的模塊內的任何一種 eval。如果 dieLevel 為 2,則調試器不關心它們來自哪裡:它會篡奪您的異常處理程序並打印一個追蹤,然後使用自己的修飾修改所有異常。這可能對某些追蹤目的有用,但往往會無情地摧毀任何對其異常處理嚴肅的程序。

AutoTrace

跟蹤模式(類似於 t 命令,但可以放入 PERLDB_OPTS)。

LineInfo

要打印行號信息的文件或管道。如果它是一個管道(比如,|visual_perl_db),那麼將使用一條短消息。這是與客戶端編輯器或可視化調試器(如特殊的 viemacs 鉤子,或者 ddd 圖形調試器)進行交互的機制。

inhibit_exit

如果為 0,允許從腳本末尾 跳出

PrintRet

當設定了r命令後,顯示返回值(默認)。

ornaments

影響命令行的屏幕外觀(參見Term::ReadLine)。目前尚無法停用這些功能,這可能會使一些顯示器或分頁器上的輸出變得不可讀。這被視為一個錯誤。

frame

影響進入和退出子程序時的消息打印。如果frame & 2為false,則只在進入時打印消息。(如果與其他消息交錯,則在退出時打印可能會有用。)

如果frame & 4,則打印函數的參數,加上上下文和調用者信息。如果frame & 8,則打印了打印的參數上啟用了重載stringifytied FETCH。如果frame & 16,則打印子程序的返回值。

參數列表截斷的長度由下一個選項管理

maxTraceLen

frame選項的位4被設置時,截斷參數列表的長度。

windowSize

更改代碼列表窗口的大小(默認為10行)。

以下選項影響VXx命令的操作

arrayDepth, hashDepth

僅打印前N個元素(''代表所有)。

dumpDepth

當轉儲結構時,限制遞歸深度為N級。負值被解釋為無限。默認值:無限。

compactDump, veryCompact

更改陣列和哈希輸出的樣式。如果compactDump,可能會將短陣列打印在一行上。

globPrint

是否打印全域變數的內容。

DumpDBFiles

轉儲包含調試文件的陣列。

DumpPackages

轉儲包的符號表。

DumpReused

轉儲“重複使用”的地址的內容。

引述, HighBit, undefPrint

更改字符串转储的样式。 引述 的默认值为 auto; 通过将其设置为 "',可以启用双引号或单引号格式。默认情况下,将以原样打印具有高位设置的字符。

僅用法

基本的按包内存使用情况转储。计算包中变量中找到的字符串的总大小。这不包括模块文件范围内的词法变量,或在闭包中丢失的变量。

歷史檔案

在调试器启动时将读取历史记录(假设有可用的 Term::ReadLine 后端)的文件路径,并在关闭时将其保存(以便跨会话持久保存)。与 Bash 的 .bash_history 文件概念类似。

歷史大小

历史记录中保存的行数(假设上述有 HistFile)。

在读取 rc 文件后,调试器读取 $ENV{PERLDB_OPTS} 环境变量,并将其解析为“O ...”行的剩余部分,就像在调试器提示符中输入一样。您可以在那里放置初始化选项 TTY, noTTY, ReadLine, 和 NonStop

如果您的 rc 文件包含

parse_options("NonStop=1 LineInfo=db.out AutoTrace");

那么您的脚本将在没有人工干预的情况下运行,将跟踪信息放入文件 db.out 中。(如果中断它,则最好将 LineInfo 重置为 /dev/tty,以便看到任何信息。)

終端機

用于调试 I/O 的终端。

無終端機

如果设置,调试器将进入 NonStop 模式,并且不会连接到终端。如果被中断(或者通过从 Perl 脚本显式设置 $DB::signal 或 $DB::single 到调试器),它将连接到启动时在 TTY 选项中指定的终端,或者在运行时使用您选择的 Term::Rendezvous 模块找到的终端。

此模块应实现一个名为 new 的方法,返回具有两个方法的对象:INOUT。这些应分别返回用于调试输入和输出的文件句柄。 new 方法应在启动时检查一个参数,其中包含 $ENV{PERLDB_NOTTY} 的值,否则为 "$ENV{HOME}/.perldbtty$$"。该文件不会检查正确的所有权,因此理论上可能存在安全隐患。

讀取行

如果为假,则禁用调试器中的 readline 支持,以便调试自身使用 ReadLine 的应用程序。

NonStop

If set, the debugger goes into non-interactive mode until interrupted, or programmatically by setting $DB::signal or $DB::single.

Here's an example of using the $ENV{PERLDB_OPTS} variable

$ PERLDB_OPTS="NonStop frame=2" perl -d myprogram

That will run the script myprogram without human intervention, printing out the call tree with entry and exit points. Note that NonStop=1 frame=2 is equivalent to N f=2, and that originally, options could be uniquely abbreviated by the first letter (modulo the Dump* options). It is nevertheless recommended that you always spell them out in full for legibility and future compatibility.

Other examples include

$ PERLDB_OPTS="NonStop LineInfo=listing frame=2" perl -d myprogram

which runs script non-interactively, printing info on each entry into a subroutine and each executed line into the file named listing. (If you interrupt it, you would better reset LineInfo to something "interactive"!)

Other examples include (using standard shell syntax to show environment variable settings)

$ ( PERLDB_OPTS="NonStop frame=1 AutoTrace LineInfo=tperl.out"
    perl -d myprogram )

which may be useful for debugging a program that uses Term::ReadLine itself. Do not forget to detach your shell from the TTY in the window that corresponds to /dev/ttyXX, say, by issuing a command like

$ sleep 1000000

See "Debugger Internals" in perldebguts for details.

Debugger Input/Output

Prompt

The debugger prompt is something like

DB<8>

or even

DB<<17>>

where that number is the command number, and which you'd use to access with the built-in csh-like history mechanism. For example, !17 would repeat command number 17. The depth of the angle brackets indicates the nesting depth of the debugger. You could get more than one set of brackets, for example, if you'd already at a breakpoint and then printed the result of a function call that itself has a breakpoint, or you step into an expression via s/n/t expression command.

Multiline commands

If you want to enter a multi-line command, such as a subroutine definition with several statements or a format, escape the newline that would normally end the debugger command with a backslash. Here's an example

DB<1> for (1..4) {         \
cont:     print "ok\n";   \
cont: }
ok
ok
ok
ok

Note that this business of escaping a newline is specific to interactive commands typed into the debugger.

Stack backtrace

以下是透過 T 命令得到的堆疊回溯的示例

$ = main::infested called from file 'Ambulation.pm' line 10
@ = Ambulation::legs(1, 2, 3, 4) called from file 'camel_flea'
                                                         line 7
$ = main::pests('bactrian', 4) called from file 'camel_flea'
                                                         line 4

上面的左方字符表示了函數被調用的上下文,其中 $@ 分別表示標量或列表上下文,而 . 表示空上下文(實際上是一種標量上下文的一種)。上面的顯示表明在執行堆疊轉儲時,您在函數 main::infested 中,並且它是在文件 Ambulation.pm 的第 10 行從標量上下文中調用的,但完全沒有任何參數,這意味著它被調用為 &infested。下一個堆疊框架顯示函數 Ambulation::legs 是從文件 camel_flea 中以列表上下文被調用,帶有四個參數。最後一個堆疊框架顯示 main::pests 也是在 camel_flea 中以標量上下文被調用,但是是從第 4 行。

如果您在活動的 use 語句內部執行 T 命令,則回溯將包含 require 框架和 eval 框架。

行列表格式

這顯示了 l 命令可以生成的輸出類型

  DB<<13>> l
101:        @i{@i} = ();
102:b       @isa{@i,$pack} = ()
103             if(exists $i{$prevpack} || exists $isa{$pack});
104     }
105
106     next
107==>      if(exists $isa{$pack});
108
109:a   if ($extra-- > 0) {
110:        %isa = ($pack,1);

可中斷的行使用 : 標記。帶有斷點的行使用 b 標記,具有動作的行使用 a 標記。即將執行的行使用 ==> 標記。

請注意,調試器列表中的代碼可能與您的原始源代碼不同。行指示和外部源過濾器可以在 Perl 看到代碼之前改變代碼,導致代碼移動到其原始位置或採取完全不同的形式。

框架列表

當設置 frame 選項時,調試器會以不同的樣式打印輸入(和可選的退出)子例程。請參見 perldebguts 以獲取這些的極長示例。

調試編譯時語句

如果您有編譯時可執行的語句(例如在 BEGIN、UNITCHECK 和 CHECK 塊中的代碼或 use 語句中的代碼),則這些將不會被調試器停止,雖然 require 和 INIT 塊會被停止,並且可以使用在 PERLDB_OPTS 中設置的 AutoTrace 選項跟踪編譯時語句)。但是,從您自己的 Perl 代碼中,您可以使用以下語句將控制權返回到調試器,如果調試器未運行,則這是無害的

$DB::single = 1;

如果將 $DB::single 設置為 2,則等效於只輸入了 n 命令,而值為 1 則表示 s 命令。將 $DB::trace 變量設置為 1 可以模擬輸入 t 命令。

調試編譯時代碼的另一種方法是啟動調試器,並在某個模塊的 load 上設置斷點

  DB<7> b load f:/perllib/lib/Carp.pm
Will stop on load of 'f:/perllib/lib/Carp.pm'.

然後使用R命令重新啟動調試器(如果可能)。 可以使用b compile subname來達到同樣的目的。

調試器自定義

調試器可能包含足夠的配置鉤子,您可能永遠不需要自行修改它。 您可以通過調試器內部的o命令,通過命令行通過PERLDB_OPTS環境變量,以及從自定義文件中更改調試器的行為。

您可以通過設置一個.perldb文件來進行一些自定義,其中包含初始化代碼。 例如,您可以製作這樣的別名(最後一個是人們期望存在的)

$DB::alias{'len'}  = 's/^len(.*)/p length($1)/';
$DB::alias{'stop'} = 's/^stop (at|in)/b/';
$DB::alias{'ps'}   = 's/^ps\b/p scalar /';
$DB::alias{'quit'} = 's/^quit(\s*)/exit/';

您可以使用這樣的調用從.perldb更改選項;

parse_options("NonStop=1 LineInfo=db.out AutoTrace=1 frame=2");

代碼在包DB中執行。 請注意,.perldb在處理PERLDB_OPTS之前被處理。 如果.perldb定義了子程序afterinit,則在調試器初始化結束後調用該函數。.perldb可以包含在當前目錄中,也可以包含在主目錄中。 由於此文件由Perl引入並且可能包含任意命令,出於安全考慮,它必須由超級用戶或當前用戶擁有,並且除其所有者外不得寫入。

您可以通過將任意命令添加到@DB::typeahead來模擬TTY輸入到調試器。 例如,您的.perldb文件可能包含

sub afterinit { push @DB::typeahead, "b 4", "b 6"; }

這將在調試器初始化後立即嘗試在第4行和第6行設置斷點。 請注意,@DB::typeahead不是受支持的界面,並且可能在將來的版本中發生變化。

如果您想修改調試器,請將perl5db.pl從Perl庫複製到另一個名稱並將其修改為您的需要。 然後,您將想要將您的PERL5DB環境變量設置為類似於這樣的內容

BEGIN { require "myperl5db.pl" }

作為最後的手段,您還可以使用PERL5DB通過直接設置內部變量或調用調試器函數來自定義調試器。

請注意,此文檔中未記錄的任何變量和函數(或perldebguts中未記錄的)僅供內部使用,因此可能會在不事先通知的情況下進行更改。

調試器中的Readline支持/歷史

預設情況下,提供的唯一命令行歷史是一個簡單的檢查前導驚嘆號的檢查。 但是,如果您從CPAN(如Term::ReadLine::GnuTerm::ReadLine::Perl等)安裝了Term::ReadKeyTerm::ReadLine模塊,您將具有完整的編輯功能,類似於GNU readline(3)提供的功能。 在CPAN的modules/by-module/Term目錄中查找這些。 但是,這些不支持正常的vi命令行編輯。

還提供了一個基本的命令行完成,包括如果安裝了PadWalker模塊,則包括當前作用域中的詞彙變量。

如果沒有Readline支持,當使用箭頭鍵和/或退格鍵時,您可能會看到符號"^[[A","^[[C","^[[B","^[[D"","^H"等。

編輯器支援除錯

如果您的系統安裝了 GNU 版本的 emacs,它可以與 Perl 調試器互動,提供一個集成的軟體開發環境,類似於它與 C 調試器的交互作用。

最新版本的 Emacs 都附帶了一個啟動文件,使 emacs 行為類似於一個語法導向的編輯器,能夠理解 Perl 的一部分語法。參見 perlfaq3

使用 vi 的用戶還應該看看 vimgvim,這是鼠標和窗口版本,可以對 Perl 關鍵字進行著色。

請注意,只有 perl 能夠真正解析 Perl,因此所有這些 CASE 工具在某種程度上都無法完全滿足要求,特別是如果您不像 C 程序員那樣編寫 Perl 程序時。

Perl 分析器

如果您希望為 Perl 提供替代的調試器運行,請在調用腳本時使用冒號和給定給 -d 標誌的包參數。Perl 的替代調試器包括 Perl 分析器,Devel::NYTProf,可以作為 CPAN 發行版單獨提供。要分析您的 Perl 程序文件 mycode.pl,只需輸入

$ perl -d:NYTProf mycode.pl

當腳本終止時,分析器將創建一個包含分析信息的數據庫,您可以使用分析器的工具將其轉換為報告。有關詳細信息,請參見 <perlperf>。

調試正則表達式

use re 'debug' 可以讓您查看 Perl 正則表達式引擎的詳細運行情況。為了理解這個通常龐大的輸出,您不僅需要對正則表達式匹配的一般運作方式有一定了解,還需要知道 Perl 的正則表達式是如何內部編譯成自動機的。這些內容在 perldebguts 中的“調試正則表達式” 中有詳細介紹。

調試內存使用

Perl 包含內部支援來報告自己的內存使用情況,但這是一個相當高級的概念,需要一些對內存分配方式的理解。有關詳細信息,請參見 perldebguts 中的“調試 Perl 內存使用”

參見

您確定已啟用了 use strictuse warnings 嗎?

perldebtut, perldebguts, perl5db.pl, re, DB, Devel::NYTProf, Dumpvalue, 和 perlrun

在調試一個使用 #! 的腳本時,通常可以在 $PATH 中找到它,-S 選項會使 perl 在 $PATH 中搜索它,這樣您就不必輸入路徑或 which $scriptname 了。

$ perl -Sd foo.pl

問題

您無法獲取由 Perl 未編譯的函數的堆疊框架信息,例如來自 C 或 C++ 擴展的函數。

如果您在子例程中修改了 @_ 參數(例如使用 shiftpop),則堆疊回溯將不顯示原始值。

調試器目前無法與 -W 命令行開關一起工作,因為它本身存在警告。

如果您正在進行一個慢系統調用(例如 waitaccept 或從鍵盤或套接字讀取的 read),且尚未設置自己的 $SIG{INT} 處理程序,則您將無法通過 CTRL-C 返回調試器,因為調試器的 $SIG{INT} 處理程序無法理解它需要引發一個異常以退出慢系統調用。