|
|
|
|
Perl in a NutshellVon Ellen Sioever, Stephen Spainhour & Nathan Patwardhan1.Auflage November 1999 ISBN 3-89721-115-7 728 Seiten |
Natürlich schreibt jeder auf Anhieb perfekten Code. Aber bei den seltenen Gelegenheiten, wo etwas schiefgeht und Sie Probleme mit Ihrem Perl-Skript haben, gibt es einige Dinge, die Sie probieren können:
Das folgende Kapitel konzentriert sich vor allem auf den Perl-Debugger, der eine interaktive Oberfläche zur Programmausführung und -überwachung bietet. Es wird jedoch auch das DProf-Modul beschrieben sowie das dprofpp-Programm, das zu diesem Modul gehört. Zusammen können diese beiden Werkzeuge ein Zeitverbrauchsprofil Ihres Perl-Skripts erstellen. Wenn Sie schon irgendwann einmal einen Debugger benutzt haben und Ihnen Konzepte wie Breakpoints (»Unterbrechungs«- oder »Haltepunkte«) und Backtraces (»Rückverfolgungsprotokolle«) bekannt sind, werden Sie keine Probleme haben, den Perl-Debugger zu verwenden. Aber selbst wenn Sie noch nie einen Debugger benutzt haben, sollten Sie mit Hilfe der folgenden Erläuterungen der Debugger-Kommandos und etwas Probieren gut zurechtkommen.
Um ein Skript mit Hilfe des Perl-Quellcode-Debuggers auszuführen, müssen Sie lediglich die Perl-Option -d auf der Kommandozeile angeben:
perl -d meinProgramm
Dies startet Ihr Programm in einer interaktiven Umgebung, in der Sie Debugger-Kommandos eingeben können, den Quellcode auflisten, Haltepunkte setzen, Stack-Backtraces bekommen, den Inhalt von Variablen ausgeben und verändern können usw. Falls Ihr Programm irgendwelche Optionen oder Parameter benötigt, können Sie diese wie üblich auf der Kommandozeile mit angeben:
perl -d meinProgramm meinInput
Im Unterschied zu den meisten anderen typischen Programmierumgebungen ist in Perl der Debugger kein separates Programm. Vielmehr weist die -d-Option den Compiler an, Quellcode-Informationen an den von ihm erzeugten Parse-Baum anzuhängen (der dann von dem Interpreter ausgeführt wird). Das bedeutet natürlich auch, daß Ihr Code sich erst einmal korrekt kompilieren lassen muß, bevor er überhaupt mit Hilfe des Debuggers ausgeführt werden kann; der Debugger wird gar nicht erst starten, solange nicht alle Kompilierungsfehler behoben sind.
Nachdem Ihr Code kompiliert ist und der Debugger gestartet wurde, wird die Ausführung vor der ersten ausführbaren Anweisung Ihres Programms angehalten. (Dies gilt nicht für Anweisungen, die bereits zur Kompilierzeit ausgeführt werden. Siehe dazu auch den Abschnitt »Benutzung des Debuggers« weiter unten.) Der Debugger zeigt die entsprechende Zeile Ihres Programms an und wartet dann auf die Eingabe eines Kommandos. Immer wenn der Debugger anhält und eine Zeile des Programms anzeigt, handelt es sich dabei um die nächste auszuführende Anweisung und nicht um die Anweisung, die er gerade ausgeführt hat.
Jede Eingabe, die der Debugger nicht als ein gültiges Debugger-Kommando erkennt, wird von ihm als eine Perl-Anweisung interpretiert, die er sofort (im Kontext des gerade ablaufenden Programms, d.h. vor allem auch im Kontext des jeweils gerade aktiven Packages) ausführt. Um vom Debugger erkannt zu werden, müssen alle Debugger-Kommandos am Beginn der Zeile anfangen. Kommandos mit führenden Leerzeichen werden von ihm automatisch als Perl-Anweisungen angesehen.
Der Debugger kennt die folgenden Kommandos:
a [Zeile] KommandoDefiniert eine Aktion, die vor der Ausführung der Zeile (falls nicht angegeben, der aktuellen Zeile) stattfinden soll. Der Compiler führt dann beim Erreichen dieser Zeile folgende Schritte aus:
Das folgende Beispiel druckt jedesmal »
DEBUGGER FAND« sowie den Wert der Variablen$foo, sobald die Zeile 53 erreicht wird:
a 53 print "DEBUGGER FAND $foo\n"
A
Löscht alle vereinbarten Aktionen.
b [Zeile] [Bedingung]
Setzt an der Zeile (falls nicht angegeben, an der aktuellen Zeile) einen Haltepunkt. Die Zeile muß eine ausführbare Anweisung enthalten (keine Variablendeklaration beispielsweise). Falls eine Bedingung Bedingung angegeben ist, wird an diesem Haltepunkt nur angehalten, falls die Bedingung zu diesem Zeitpunkt (d.h. beim Erreichen des Haltepunkts) erfüllt ist:
b 237 $x > 30 b 33 /Muster/i
b Subroutine [Bedingung]
Setzt einen Haltepunkt vor der ersten ausführbaren Anweisung der Subroutine namens Subroutine, ggfs. geknüpft an eine Bedingung Bedingung.
b load Dateiname
Setzt einen Haltepunkt an der ersten ausführbaren Anweisung in der Datei Dateiname, die mit Hilfe von
requiregeladen wird.
b postpone Subroutine [Bedingung]
Setzt einen Haltepunkt (möglicherweise an eine Bedingung geknüpft) an der ersten ausführbaren Anweisung der Subroutine, nachdem diese kompiliert worden ist.
b compile Subroutine
Hält an, sobald die Subroutine kompiliert wurde.
c [Zeile | Subroutine]
Setzt die unterbrochene Ausführung fort (continue). Setzt außerdem wahlweise einen Einmal-Haltepunkt an der angegebenen Zeile oder am Anfang der angegebenen Subroutine.
d [Zeile]
Löscht (delete) den Haltepunkt an der Zeile. Falls die Zeilenangabe Zeile fehlt, wird der Haltepunkt an der aktuellen (auf ihre Ausführung wartende) Zeile gelöscht.
D
Löscht alle gesetzten Haltepunkte.
f Dateiname
Schaltet die Sicht auf die Datei Dateiname um.
h [Kommando]
Gibt eine Hilfe, d.h. die Liste aller verfügbaren Debugger-Kommandos, aus. Falls ein Kommando angegeben ist, wird statt dessen eine Beschreibung des betreffenden Debugger-Kommandos ausgegeben. Das spezielle Kommando
h herzeugt eine kürzere Kommandoübersicht, die für kleinere Bildschirmfenster gedacht ist und ganz auf den Bildschirm passen soll.
H [-Anzahl]
Zeigt die Kommando-Historie an. Falls eine Anzahl angegeben ist, werden nur die Anzahl letzten Komandos aufgelistet. Es werden aber in jedem Falle nur Kommandos angezeigt, die länger als ein Buchstabe sind.
l [Zeilenangabe]
Falls Zeilenangabe fehlt, werden die nächsten paar (zur Ausführung anstehenden) Zeilen Ihres Programms aufgelistet. Ansonsten werden diejenigen Zeilen aufgelistet, die durch Zeilenangabe beschrieben werden. Diese Zeilenangabe kann eine der folgenden Formen annehmen:
Zeile
Zeigt die Zeile an, deren Zeilennummer Zeile angegeben wurde.
start+offset
Listet offset
+1Zeilen auf, beginnend bei Zeile start.
start-stop
Listet alle Zeilen beginnend bei start bis einschließlich stop auf.
Subroutine
Listet die ersten paar Zeilen der Subroutine auf.
Siehe auch die Kommandos
wund-.
L
Listet alle Haltepunkte und Aktionen auf, die in der gerade ausgeführten Datei definiert wurden.
m Ausdruck
Der Ausdruck Ausdruck wird (mit Hilfe von
eval) im Listen-Kontext ausgewertet. Anschließend werden alle Methoden ausgegeben, die sich auf das Ergebnis der Auswertung anwenden lassen.
m Klasse
Listet alle verfügbaren Methoden der Klasse auf.
n
Das »Next«-Kommando (»Nächste Anweisung«) führt die nächste auf ihre Ausführung wartende Zeile (im Einzelschritt-Modus) aus. Dabei werden Aufrufe von Subroutinen jedoch als ein einziger elementarer Befehl behandelt, d.h., es wird erst wieder an der Anweisung nach dem Aufruf der Subroutine angehalten (im Gegensatz zum
s- Kommando).
O [Option[=Wert]] [Option'Wert'] [Option?]
Fragt den Wert von Optionen ab oder setzt einen neuen Wert. Falls Wert weggelassen wird, wird der Wert
1verwendet. Option? zeigt den augenblicklichen Wert der Option an. Der Name einer Option kann dabei auch abgekürzt (d.h. nach den ersten paar Buchstaben abgeschnitten) werden, solange diese Abkürzung eindeutig bleibt. Es können auch mehrere Optionen auf derselben Zeile angegeben und bearbeitet werden. Die möglichen Optionen sind:
AutoTrace
Beeinflußt die Ausgabe von Nachrichten an jedem möglichen Haltepunkt.
frame
Schaltet die Ausgabe von Nachrichten beim Eintritt in und bei der Rückkehr aus Subroutinen ein.
inhibit_exit
Erlaubt es, ohne automatische Beendigung des Debuggers über das Ende des Skripts hinauszuschreiten.
maxTraceLen
Legt die maximale Länge für die Ausgabe von Argumentlisten und
eval-Anweisungen bei Stack-Traces fest.
ornaments
Beeinflußt das Aussehen der Kommandozeile auf dem Bildschirm.
pager
Legt das »Pager«-Programm (z.B. »more« oder »less«) fest, in das die Ausgabe von Kommandos umgeleitet werden soll, denen ein
|-Zeichen vorangestellt wurde. Die Voreinstellung für diese Option ist$ENV{PAGER}.
PrintRet
Schaltet die Anzeige des Rückgabewerts von
r-Kommandos ein.
recallCommand,ShellBang
Diese beiden Optionen legen das Zeichen fest, mit dem man zurückliegende Kommandos erneut aufrufen bzw. mit dem man eine temporäre Shell öffnen kann. Beide Variablen sind zu Beginn auf
!voreingestellt.
Die folgenden Optionen steuern das Verhalten des
V-,X- undx-Kommandos:
arrayDepth,hashDepth
Beschränkt die Ausgabetiefe auf n (der Wert "" bedeutet keinerlei Einschränkung).
compactDump,veryCompact
Verändert das Ausgabeformat für Arrays und Hashes.
DumpDBFiles
Gibt Arrays aus, die Dateien enthalten, die gerade debuggt werden.
DumpPackages
Gibt die Symboltabellen von Packages aus.
globPrint
Legt fest, ob der Inhalt von Globs auch ausgegeben werden soll.
quote,HighBit,undefPrint
Verändert das Ausgabeformat für Strings.
signalLevel,warnLevel,dieLevel
Legt den Ausführlichkeitsgrad (»verbosity«) von Meldungen fest.
tkRunning
Bedient sich bei der Eingabeaufforderung von Kommandozeilen (mit ReadLine) der Graphikbibliothek »Tk«.
Beim Starten werden die Optionen des Debuggers aus der Umgebungsvariablen PERLDB_OPTS (d.h.
$ENV{PERLDB_OPTS}) initialisiert. Dort können Sie außerdem noch die speziellen InitialisierungsoptionenTTY,noTTY,ReadLineundNonStopsetzen. Weitere Informationen zu diesem Thema finden Sie im Abschnitt »Anpassen des Debuggers« weiter unten in diesem Kapitel.
p Ausdruck
Bewirkt dasselbe wie ein
print DB::OUTAusdruck im Kontext des aktuellen Packages. Das bedeutet insbesondere, daß verschachtelte Datenstrukturen und Objekte im Gegensatz zumx-Kommando nicht aufgelöst, d.h. ihre Bestandteile nicht mit ausgegeben werden. Das Dateihandle DB::OUT ist dabei immer mit /dev/tty (bzw. einem Editor-Fenster) verbunden, unabhängig davon, ob und wohin die Standardausgabe umgeleitet wurde.
q oder ^D
Beendet den Debugger (quit).
r
Bewirkt den Rücksprung aus der aktuellen Subroutine.
R
Startet den Debugger neu (Restart). Es wird dabei versucht, soviel wie möglich von Ihrer Historie von einer Session (Sitzung) zur nächsten zu retten, aber einige interne Einstellungen sowie Kommandozeilenoptionen können verlorengehen.
s [Ausdruck]
Das Einzelschritt-Kommando (Single Step) führt die nächste auf ihre Ausführung wartende Zeile aus. Die Ausführung hält anschließend an der nächsten darauffolgenden ausführbaren Anweisung wieder an. Dabei verzweigt der Debugger bei Unterprogrammaufrufen in die entsprechende Subroutine und hält dort an (im Gegensatz zum
n-Kommando). Falls ein Ausdruck angegeben ist, wird dieser ausgewertet, und alle Unterprogrammaufrufe in diesem Ausdruck werden im Einzelschritt-Modus ausgeführt.
S [[!]Muster]
Listet alle Subroutinen auf, deren Namen auf das Muster passen (oder nicht passen, falls
!angegeben wurde). Falls das Muster fehlt, werden alle Subroutinen aufgelistet.
t
Schaltet den Trace-Modus ein und aus.
t Ausdruck
Wertet den Ausdruck aus und protokolliert seine Ausführung.
T
Erstellt ein Rückverfolgungsprotokoll für den Stack; zum Beispiel:
DB<2> T
$ = main::verpestet called from file `Heimsuchung.pm' line 10
@ = Heimsuchung::beine(1, 2, 3, 4) called from file `kamel_floh' line 7
$ = main::plagen('bakterielle', 4) called from file `kamel_floh' line 4Das Zeichen am linken Rand (
$oder@) zeigt dabei an, ob die betreffende Funktion im Skalar- oder Listenkontext aufgerufen wurde. Das Beispiel zeigt drei Zeilen an, da der Debugger sich gerade an einer Stelle befand, die drei Ebenen (Funktionsaufrufe) tief verschachtelt war, als das Trace-Kommando eingegeben wurde.
v
Zeigt die Versionsnummern (falls verfügbar) und die Pfade aller gerade geladenen Module an.
V [Package [Variablen]]
Zeigt alle (oder nur einige) Variablen aus dem Package an. Es verwendet dazu ein »Pretty- Printer«-Modul, das Schlüssel und Werte von Hashes in übersichtlicher Weise darzustellen vermag. Es kann auch nicht druckbare Kontrollzeichen, geschachtelte Datenstrukturen usw. sichtbar machen. Falls Package fehlt, wird automatisch das Package
mainangenommen. Bei den Variablennamen Variablen ist eine Besonderheit zu beachten: Diese müssen ohne das vorangehende Typkennzeichen (wie$oder@) angegeben werden:
V DB filename lineStatt eines Variablennamens können Sie auch einen regulären Ausdruck verwenden, wie z.B.
~Muster oder!Muster. Dann werden alle Variablen aufgelistet, deren Namen auf das Muster passen (bzw. nicht passen).
w [Zeile]
Zeigt ein Fenster (window) an, das aus einer Reihe von Zeilen besteht, die sich über und unter der aktuellen Zeile oder der Zeile befinden, falls diese angegeben ist.
x Ausdruck
Der Ausdruck wird (mit Hilfe von
eval) im Listenkontext ausgewertet, und das Ergebnis wird mit Hilfe des »Pretty-Printer«-Moduls aufbereitet ausgegeben. Im Unterschied zu dem weiter oben beschriebenen p- bzw. »print«-Kommando werden bei diesem Kommando auch die Bestandteile von verschachtelten Datenstrukturen rekursiv mit ausgegeben.
X [Variablen]
Dasselbe wie V aktuellespackage [Variablen].
<CR>
Wiederholt das letzte
n- oders-Kommando.
-
Listet ein paar der vor der aktuellen Anweisung liegenden Zeilen auf.
.
Setzt den Debugger auf die zuletzt ausgeführte Zeile zurück und gibt diese aus.
/Muster/
Sucht vorwärts nach dem Muster. Der abschließende Schrägstrich
/darf auch weggelassen werden.
?Muster?
Sucht rückwärts nach dem Muster. Das abschließende Fragezeichen
?darf auch weggelassen werden.
< [Kommando]
Definiert ein Perl-Kommando, das unmittelbar vor jeder Eingabeaufforderung des Debuggers ausgeführt werden soll. Ein mehrzeiliges Kommando kann dadurch eingegeben werden, daß vor jedem <CR> ein Backslash (
\) eingegeben wird. Falls das Kommando fehlt, werden alle ggfs. vorher definierten Kommandos wieder gelöscht.
<< [Kommando]]
Fügt der Liste von Perl-Kommandos, die unmittelbar vor jeder Eingabeaufforderung des Debuggers ausgeführt werden sollen, ein weiteres Kommando hinzu.
> [Kommando]
Definiert ein Perl-Kommando, das unmittelbar nach jeder Eingabeaufforderung des Debuggers (aber noch vor der Ausführung des gerade per Eingabeaufforderung erteilten Kommandos) ausgeführt werden soll. Ein mehrzeiliges Kommando kann dadurch eingegeben werden, daß vor jedem <CR> ein Backslash (
\) eingegeben wird. Falls das Kommando fehlt, werden alle ggfs. vorher definierten Kommandos wieder gelöscht.
>> [Kommando]
Fügt der Liste von Perl-Kommandos, die unmittelbar nach jeder Eingabeaufforderung des Debuggers ausgeführt werden sollen, ein weiteres Kommando hinzu.
{ [Kommandozeile]
Definiert ein Debugger-Kommando, das unmittelbar vor jeder Eingabeaufforderung ausgeführt werden soll.
{{ [Kommandozeile]
Fügt ein weiteres Kommando zu der Liste von Debugger-Kommandos hinzu, die unmittelbar vor jeder Eingabeaufforderung ausgeführt werden sollen.
! [nummer]
Führt ein früheres Kommando erneut aus (das unmittelbar vorhergehende, falls nummer fehlt).
! -nummer
Führt das nummer-letzte Kommando (d.h.
1= letzte,2= vorletzte usw.) erneut aus.
! Muster
Führt das letzte Kommando, das mit dem Muster beginnt, erneut aus. Siehe dazu auch
O recallCommand.
!! Kommando
Führt das Kommando in einem Subprozeß aus (der von DB::IN liest und nach DB::OUT schreibt). Siehe dazu auch
O ShellBang.
| Debugger-Kommando
Führt das angegebene Debugger-Kommando aus und leitet dessen Ausgabe von DB::OUT zum vorher festgelegten »Pager«-Programm um. Siehe dazu auch
O pager. Wird oft im Zusammenhang mit Kommandos benutzt, die eine sehr lange Ausgabe erzeugen, wie im folgenden Beispiel:
|V main
|| Kommando
Dasselbe wie
|Kommando, jedoch wird zusätzlich DB::OUT mit Hilfe vonselectzum Standarddateihandle für die Ausgabe erklärt.
= [Aliasname Definition]
Definiert einen Aliasnamen für ein Kommando, z.B.
= quit q. Falls der Aliasname und die Definition fehlen, werden alle existierenden Aliase aufgelistet.
Kommando[;]
Falls Kommando kein Debugger-Kommando ist, wird es als eine Perl-Anweisung interpretiert und als solche ausgeführt. Das abschließende Semikolon kann auch weggelassen werden.
Beachten Sie, daß Anweisungen in Ihrem
Programm, die von Perl bereits zur Kompilierzeit ausgeführt werden (wie
z.B. ein BEGIN-Block oder eine use-Anweisung) nicht
mit Hilfe des Debuggers Schritt für Schritt durchgegangen werden können,
da diese bereits ausgeführt werden, bevor der Debugger die Kontrolle über
die Programmausführung erlangt. (Dies gilt nicht für require-Anweisungen,
da diese im Gegensatz zu use erst zur Laufzeit ausgeführt
werden.)
Die Eingabeaufforderung des Debuggers sieht in etwa so aus:
DB<8>
oder auch so:
DB<<17>>
Die Nummer in spitzen Klammern ist die
laufende Nummer des aktuellen Kommandos. Ein Mechanismus ähnlich wie in
der C-Shell (csh) erlaubt (mit Hilfe der Nummern) den Rückgriff
auf frühere ausgeführte Kommandos. Beispielsweise wiederholt !17
das Kommando mit der Nummer 17. Die Anzahl ineinandergeschachtelter spitzer
Klammern spiegelt dabei die Verschachtelungstiefe des Debuggers wider. Diese
Art von rekursivem Selbstaufruf des Debuggers tritt z.B. dann auf, wenn Sie
an einem Haltepunkt stehen und den Rückgabewert einer Funktion zu drucken
versuchen, die ihrerseits einen Haltepunkt enthält.
Falls Sie ein mehrzeiliges Kommando eingeben
wollen, wie z.B. die Definition einer Subroutine mit mehreren Anweisungen, so
können Sie dazu Backslashes (\) am Zeilenende einsetzen, wie
im folgenden Beispiel:
DB<1> sub hinz { \
cont: print "kunzzeile\n"; \
cont: } DB<2> hinz
kunzzeile
Sie können in Ihrem Programm sogar
eine gewisse Kontrolle über den Debugger ausüben. Sie können
zum Beispiel an einer beliebigen Stelle in Ihrem Programm einen festen Haltepunkt
setzen, der immer dann beachtet wird, wenn das Programm mit Hilfe des Debuggers
ausgeführt wird, und ansonsten keinerlei Wirkung hat. Sie erreichen dies,
indem Sie vor der betreffenden Zeile eine Anweisung $DB::single = 1;
einfügen. Der Debugger hält dann automatisch an der nächsten
ausführbaren Anweisung an, so als ob Sie das s-Kommando des
Debuggers verwendet hätten. Wenn Sie $DB::single dagegen auf
2 setzen, entspricht das dem n-Kommando. Und wenn
Sie $DB::trace auf den Wert 1 setzen, schaltet dies
analog zum t-Kommando den Trace-Modus ein.
Sie können den Debugger jederzeit
beenden (und die Programmausführung abbrechen), indem Sie an der Eingabeaufforderung
des Debuggers q eingeben oder Ctrl-D (Strg-D) drücken. Sie
können den Debugger neu starten, indem Sie R (Restart) eingeben.
Sie können den Debugger in gewissem Umfang individuell anpassen, indem Sie eine Datei namens .perldb in Ihrem Home-Verzeichnis (das Startverzeichnis nach dem Einloggen auf Ihrem Rechner) einrichten und mit Initialisierungscode füllen. Beim Starten sucht der Debugger nach dieser Datei. Falls sie existiert, lädt der Debugger diese Datei und führt sie aus. Sie können auf diese Weise zum Beispiel ein paar Aliase für oft benötigte Kommandos definieren:
$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\b.*/exit/'
Sie können diese Datei aber auch nutzen,
um einige Debugger-Optionen einzustellen oder um eine Subroutine namens afterinit
zu definieren, die nach der Initialisierung des Debuggers automatisch ausgeführt
wird.
Nachdem der Debugger diese Konfigurationsdatei
abgearbeitet hat, liest er den Inhalt der Umgebungsvariablen PERLDB_OPTS
ein (falls sie existiert) und interpretiert den Inhalt als Liste von Argumenten
für das Debugger-Kommando O opt=val.
Während alle normalen Optionen des Debuggers auch in der Umgebungsvariablen PERLDB_OPTS gesetzt werden können, gibt es umgekehrt spezielle Optionen, die ausschließlich beim Start des Debuggers (d.h. entweder in .perldb oder in PERLDB_OPTS) gesetzt werden können, nicht jedoch interaktiv im Debugger selbst. Falls Sie eine solche Option in Ihrer Konfigurationsdatei (.perldb) statt in PERLDB_OPTS setzen wollen, verwenden Sie dazu die folgende Syntax:
&parse_Options("opt=val");
Diese speziellen Optionen sind die folgenden:
TTY
Das TTY-Gerät (device), das für die Ein- und Ausgaben des Debuggers verwendet werden soll.
noTTY
Falls diese Option gesetzt ist, geht der Debugger in den NonStop-Modus. Bei einem Interrupt und falls TTY nicht gesetzt ist, nimmt der Debugger den Wert von
noTTYoder / tmp/perldbtty$$, um das TTY-Gerät (mit Hilfe von Term::Rendezvous) zu finden. Die aktuelle Variante besteht darin, den Namen des TTY-Geräts in dieser Datei zu haben.
ReadLine
Falls diese Option auf den Wert false gesetzt wird, verwendet der Debugger eine Pseudo- ReadLine-Funktion, so daß Sie auch Applikationen debuggen können, die selbst
ReadLineverwenden.
NonStop
Falls diese Option auf den Wert true gesetzt wird, finden keine Interaktionen (keine Eingabeaufforderung) statt, bis ein Interrupt aufgetreten ist.
LineInfo
Der Name einer Datei oder einer Pipe (d.h. »pipeline« oder »Warteschlange«), in der die Informationen über die Zeilennummern protokolliert werden sollen. Falls es sich um eine Pipe handelt, werden kurze, emacs-artige Nachrichten geschrieben.
Hier ein Beispiel für eine .perldb-Datei:
&parse_Options("NonStop=1 LineInfo=db.out"); sub afterinit { $trace = 1; }
Die Konfigurationsdatei aus dem obigen Beispiel sorgt dafür, daß Ihr Programm ganz ohne Benutzereingaben abläuft und alle Trace-Informationen in der Datei db.out abgelegt werden.
Sie können in Perl übrigens auch einen anderen als den eingebauten Debugger verwenden, indem Sie Ihr Programm mit der Perl-Option -d:modul starten. Eine der populärsten Debugger-Alternativen ist DProf, der Perl-Profiler. Bei Drucklegung dieses Buches war DProf noch nicht Teil der Standard-Perl-Distribution, aber das wird er vermutlich bald sein.
Bis dahin müssen Sie sich Devel::DProf selbst vom CPAN herunterladen. Sobald dieses Modul erfolgreich installiert ist, können Sie es benutzen, um ein Profil des Zeitverbrauchs in Ihrem Programm zu erstellen, so wie in dem folgenden Beispiel:
perl -d:DProf testpgm
Während Ihr Programm ausgeführt wird, sammelt DProf seine Profildaten. Sobald sich Ihr Programm beendet, schreibt DProf die gesammelten (Roh-)Daten in eine Datei namens tmon.out (im aktuellen Verzeichnis). Ein Programm namens dprofpp (das in der Devel::DProf-Distribution mit enthalten ist) kann verwendet werden, um aus diesen Daten eine Übersicht zu generieren:
% dprofpp tmon.out Total Elapsed Time = 0.15 Seconds User+System Time = 0.1 Seconds Exclusive Times %Time Seconds #Calls sec/call Name 30.0 0.030 1 0.0300 Text::Wrap::CODE(0x175f08) 20.0 0.020 1 0.0200 main::CODE(0xc7880) 20.0 0.020 1 0.0200 main::CODE(0xfe480) 10.0 0.010 1 0.0100 Text::Wrap::CODE(0x17151c)
10.0 0.010 10 0.0010 Text::Tabs::expand
0.00 0.000 1 0.0000 lib::CODE(0xfe5b8)
0.00 0.000 3 0.0000 Exporter::export
0.00 0.000 1 0.0000 Config::FETCH
0.00 0.000 1 0.0000 lib::import
0.00 0.000 1 0.0000 Text::Wrap::CODE(0x171438)
0.00 0.000 3 0.0000 vars::import
0.00 0.000 3 0.0000 Exporter::import
0.00 0.000 2 0.0000 strict::import
0.00 0.000 1 0.0000 Text::Wrap::CODE(0x171684)
0.00 0.000 1 0.0000 lib::CODE(0xfe4d4)
Diese Ausgabe zeigt die fünfzehn Subroutinen mit dem größten Zeitverbrauch. Sie können sich damit auf diejenigen Subroutinen konzentrieren, bei denen eine Optimierung des Codes den größten Nutzen (die größten Einsparungen) bringt. Das obige Beispiel wurde mit den Standardeinstellungen von dprofpp erzeugt. Das Verhalten dieses Werkzeugs kann jedoch mit Hilfe der folgenden Optionen noch genauer beeinflußt werden:
-a
Sortiert die Ausgabe alphabetisch nach dem Namen der Subroutine.
-E
Standardeinstellung. Zeigt den Netto-Zeitverbrauch von allen Subroutinen an, den Verbrauch von darin aufgerufenen Subroutinen nicht mit eingeschlossen.
-F
Erzwingt die Erzeugung von »frisierten« Ende-Zeitstempeln, falls dprofpp meldet, daß das Profil verstümmelt ist. Diese Option sollte wirklich nur dann angewendet werden, wenn dprofpp meldet, daß das Profil aufgrund fehlender Ende-Zeitstempel unbrauchbar ist.
-I
Zeigt den Zeitverbrauch aller Subroutinen einschließlich der Zeiten für darin aufgerufene weitere Subroutinen an.
-l
Sortiert nach der Anzahl von Aufrufen der jeweiligen Subroutine.
-O Anzahl
Zeigt nur die ersten Anzahl Subroutinen an. Die Voreinstellung für diese Option ist fünfzehn.
-p skript
Führt die beiden Schritte Datensammlung (Profilerstellung) und Datenauswertung (Profilanalyse) zusammen aus, d.h. man muß den Profiler DProf vor der Auswertung nicht explizit selbst starten.
-Q
Wird zusammen mit -p verwendet: Erstellt das Profil des Skripts und stoppt (quit), ohne die erzeugten Profildaten auszuwerten.
-q
Unterdrückt die Ausgabe der Spaltenüberschriften (quiet).
-r
Zeigt die verbrauchte Echtzeit (»real-time«) an.
-s
Zeigt nur Systemzeiten an.
-T
Zeigt Aufrufe von Subroutinen an, aber keine Statistiken über sie.
-t
Zeigt den Baum (tree) von Subroutinenaufrufen an, aber keine Subroutinenstatistiken. Eine Subroutine, die mehrfach aufgerufen wurde, wird nur einmal aufgeführt, jedoch mit der Anzahl der erfolgten Aufrufe.
-U
Zeigt die unsortierte Ausgabe an.
-u
Zeigt nur Benutzer-Zeitverbrauch (user-time) an.
-V
Gibt die Versionsnummer des aufgerufenen dprofpp-Programms aus.
-v
Sortiert die Ausgabe nach der durchschnittlichen Zeit (average time), die in der jeweiligen Subroutine verbracht wurde.
-z
Standardeinstellung. Sortiert nach dem Verbrauch von Benutzer- und Systemzeit, so daß die ersten paar Zeilen die Subroutinen mit dem größten Zeitverbrauch anzeigen sollten.
Es ist möglich, daß Sie während der Entwicklung und des Debuggens Ihrer eigenen Programme auf einen Fehler, einen Bug, in Perl selbst stoßen. Sollte das passieren, ist das perlbug-Programm die beste Art, den gefundenen Fehler (zur Überprüfung und ggfs. Behebung) den Perl-Entwicklern zu melden. perlbug ist ein Perl-Programm, das speziell zum Melden von Bugs in Perl geschrieben wurde. Es vereinheitlicht den Meldeprozeß und vereinfacht dadurch die Erfassung der Fehler für die Perl-Entwickler. Gleichzeitig erleichtert es dem Benutzer die Erstellung einer aussagekräftigen und vollständigen Fehlermeldung, da es interaktiv alle benötigten Angaben abfragt und außerdem automatisch alle nötigen Informationen über die verwendete Perl-Installation (d.h. ihre Konfigurationsparameter) anfügt. Sie brauchen dabei keine Angst vor einem Ausspähen Ihres Rechners zu haben, da Sie vor dem Abschicken Gelegenheit haben, alle angehängten Informationen zu überprüfen. Das Programm erzeugt eine E-Mail, die nach Ihrer Freigabe an die Adresse perlbug@perl.com verschickt wird. (Falls Sie keine der Standardportierungen von Perl verwenden, sollten Sie die mitgelieferte Dokumentation konsultieren, um herauszufinden, wie Sie dort Fehler melden können. Möglicherweise funktioniert aber das perlbug-Programm zumindest soweit, daß Sie damit die vollständige Fehlermeldung erstellen und dann abspeichern können, um sie dann auf einem anderen Weg von Hand zu verschicken. Diese Möglichkeit steht Ihnen natürlich auch insbesondere dann offen, wenn Sie auf Ihrem Rechner keine E-Mails auf direktem Weg verschicken können.) Sollten Sie für den gefundenen Fehler in Perl sogar über eine Lösung verfügen, sollten Sie diese natürlich auch unbedingt mit beifügen!
Sie sollten das perlbug-Programm nicht dazu mißbrauchen, um Hilfe beim Debuggen Ihres eigenen Programms zu bekommen. Wenden Sie sich statt dessen an die Newsgruppen und andere Ressourcen im Internet, die speziell dafür vorgesehen sind. Sie finden eine Liste dieser Einrichtungen in Kapitel 1. Wenn Sie jedoch glauben, einem Fehler in Perl selbst auf der Spur zu sein, ist das perlbug-Programm auf jeden Fall das richtige Mittel, um diesen Fehler zu melden.
Und so rufen Sie das perlbug-Programm auf (Beispiel):
% perlbug -t
Das perlbug-Programm erkennt die folgenden Optionen:
-a adresse
Die E-Mail-Adresse, an die die Fehlermeldung geschickt werden soll. Die Voreinstellung ist perlbug@perl.com.
-b beschreibung
Der vollständige Beschreibungstext der Fehlermeldung. Falls dieser Text weder (mit Hilfe dieser Option) auf der Kommandozeile eingegeben noch (mit Hilfe der Option -f) in einer Datei angegeben wird, erhalten Sie die Gelegenheit, ihn mit Hilfe eines Editors einzugeben.
-C
Sende keine Kopie (»Cc«) an den in der Perl-Konfiguration vermerkten zuständigen Perl- Administrator.
-c adresse
Die E-Mail-Adresse, an die eine Kopie der Fehlermeldung (per »Cc«) geschickt werden soll. Voreinstellung ist der in der Perl-Konfiguration vermerkte zuständige Perl- Administrator.
-d
»Data«-Modus. (Dies ist die Standardeinstellung, falls Sie die Eingabe umlenken oder in einer Pipe zur Verfügung stellen.) Gibt die erzeugte Fehlermeldung einfach nur auf der Standardausgabe aus, ohne sie abzuschicken. Benutzen Sie zusätzlich die Option -v, um noch ausführlichere Informationen zu erzeugen.
-e editor
Gibt den zu verwendenden Editor an. Standardeinstellung ist Ihr Lieblingseditor (
$ENV{EDITOR}) oder vi.
-f Datei
Gibt die Datei an, die die vollständige Fehlerbeschreibung enthält.
-h
Gibt eine Hilfe aus.
-ok
Meldet die erfolgreiche Kompilierung von Perl auf Ihrem System an die »Perl Porters«. Setzt automatisch die Optionen -S und -C; setzt außerdem die Optionen -s und -b und gibt ihnen automatisch passende Werte mit. Benutzen Sie zusätzlich die Option -v, um noch ausführlichere Informationen zu erzeugen. Die Meldung wird nur abgeschickt, falls die erfolgreiche Kompilierung von Perl weniger als 60 Tage zurückliegt.
-okay
Dasselbe wie -ok, aber es können damit auch Meldungen abgeschickt werden, wenn die Kompilierung von Perl vor mehr als 60 Tagen erfolgte.
-r adresse
Die »Reply-To:«-Adresse. Falls sie nicht auf der Kommandozeile angegeben wird, fragt perlbug danach.
-S
Schickt die Meldung ohne Rückfrage ab.
-s subject
Die »Subject:«-Zeile für die E-Mail. Falls sie nicht auf der Kommandozeile angegeben wird, fragt perlbug danach.
-t
Test-Modus. Ändert die Zieladresse in perlbug-test@perl.com um.
-v
Ausführlich (»Verbose«). Schreibt ausführlichere Konfigurationsdaten in die Fehlermeldung.
Zurück zu: Perl in a Nutshell
© 1999, O'Reilly Verlag