|
|
|
Kapitel 11 |
Einleitung
Debuggersteuerung
STOP Befehle und Breakpoints
Speicherfenster
Variablenfenster
Debuggereinstellungen
Fehlermeldungen des Debuggers
Praktische Beispiele
Einleitung
Wenn Sie bereits Computerprogramme geschrieben haben, kennen Sie sicherlich
das Problem, dass ein Programm sich anders verhält, als man es sich überlegt
hat. Ohne Hilfsmittel ist es im allgemeinen sehr schwer, einen simplen Schreibfehler
oder auch einen systematischen Fehler zu finden, da man dem Programm bei der Arbeit
nur bedingt zusehen kann.
Mit dem Source Code Debugger können Sie nun ganz gezielt auf Fehlersuche gehen.
Dazu halten Sie Ihr Programm einfach an geeigneter Stelle an und arbeiten sich in
Einzelschritten voran. Dabei können Sie verfolgen, wie sich Variablen- oder
Speicherinhalte verändern und so gezielt feststellen, an welcher Stelle sich
Ihr Programm anders verhält, als geplant. Ein kleines Dreick im Quellcode zeigt
beim Debuggen ständig die aktuelle Position des Programmzeigers.
Aber auch für didaktische Zwecke ist der Source Code Debugger bestens geeignet.
Lehrer können durch die Einzelschritttechnik Ihren Schülern auf einfache
Weise vermitteln, wie ein Algorithmus funktioniert.
Hierfür gibt es auch noch den Animationsmodus, bei dem ein Programm sozusagen
in Zeitlupe ausgeführt wird, so dass man die einzelnen Schritte genau verfolgen
kann.
Debuggersteuerung
Um ein Programm debuggen zu können, müssen Sie zunächst das
Fenster mit dem Quellcode nach oben holen und dann den Menüpunkt 'Debuggen'
aus dem 'Programm' Menü anwählen. Das Programm wird dadurch in einem speziellen
Format compiliert, das es dem Debugger ermöglicht, jederzeit den Programmablauf
zu kontrollieren. Dabei werden auch noch ständig folgende mögliche Fehlerquellen
überwacht:
- Integer-Überläufe bei Byte-, Integer- und Long-Integer-Zahlen. Z. B. würde A%=32768 oder A%L=10^12 einen solchen Fehler auslösen.
- Fliesskomma-Überläufe und Fliesskomma-Unterläufe. Diese Fehler treten auf, wenn das Ergebnis einer Rechnung in dem verwendeten Zahlenformat nicht dargestellt werden kann (z.B. A#=10^100*10^250 oder A!=10^-45).
- Divisionen durch Null.
- Unerlaubte Operation wie z. B. A#=LN(-1).
- Überlauf des BASIC-Stacks. Dies kann z.B. beim Sortieren grösserer Felder oder bei rekursiever Programmierung mit grosser Schachteltiefe auftreten.
- Bei Feldvariablen wird überprüft, ob die angegebenen Indizes im dem Bereich liegen, für den das Feld dimensioniert wurde. Z. B. DIM A#(2,3):A#(3,2)=1 würde einen solchen Fehler auslösen.
Wenn einer dieser Fehler auftritt, wird zunächst eine Alertbox angezeigt, die den Fehler beschreibt. Nach Verlassen der Alertbox erscheint die Debuggersteuerung. Sie können jetzt Speicher- und Variablenfenster öffnen und so herausfinden, wodurch der Fehler entstanden ist. Falls es sich nicht um einen fatalen Fehler handelt, kann das Programm sogar fortgesetzt werden, andernfalls wird es in jedem Fall beendet, auch wenn Sie versuchen, es fortzusetzen.
Natürlich gibt es noch viele weitere Fallen, in die ein Programmierer tappen kann und die vom Debugger prinzipbedingt nicht erkannt werden können (z. B. LPOKE 12,-1 oder wenn Sie die Extension Library verwenden, aber am Programmanfang Extension_Init vergessen haben). Bitte nicht ausprobieren, da dies mit ziemlicher Sicherheit zum Absturz Ihres Computers führt.
Damit der Debugger all diese Aufgaben erfüllen kann, wird eine Tabelle angelegt, die eine Beziehung herstellt zwischen dem Quellcode und dem vom Compiler erzeugten Objektcode. Darum kann das Programm während der Debuggingphase nicht editiert werden. Denken Sie also nicht, dass Ihr Computer abgestürzt ist, weil Sie plötzlich nichts mehr an Ihrem Programm ändern können.
Nach der Compilierung wird das Programm automatisch gestartet. Wegen des zusätzlichen
Verwaltungsaufwands laufen die mit 'Debuggen' erzeugten Programme etwas langsamer,
als wenn man den Menüpunkt 'Compilieren & Starten' verwendet. Das sollte
bei der Fehlersuche aber keine Rolle spielen.
Hinweis: Wenn Sie mit der Lite-Version oder gar
der Demo-Version arbeiten, kann es passieren, dass sich ein Programm zwar normal
compilieren, aber nicht debuggen lässt. Dies liegt daran, dass im Debugmodus
zusätzlicher Objectcode erzeugt wird, so dass das compilierte Programm zu lang
wird für die Lite-Version bzw. die Demo-Version.
Nachdem Ihr Programm vom Debugger gestartet wurde, öffnet sich ein kleines Fenster
mit der Debuggersteuerung. Das Fenster enthält 7 Buttons, mit denen Sie den
Ablauf Ihres Programms beeinflussen können. Im einzelnen gibt es die folgenden
Steuerungsmöglichkeiten.
[Anhalten]
Wenn Sie auf diesen Knopf klicken, wird Ihr Programm sofort angehalten. Dabei
scrollt das Fenster mit dem Quellcode automatisch an die Stopstelle, die durch ein
kleines Dreieck markiert wird. Diese Funktion kann auch durch [Ctrl]+[C] ausgelöst
werden.
Achtung: Wenn Ihr Programm keine regelmässigen COMPILER "EVENT" oder EasyMesag Aufrufe (im Falle einer Programmierung mit EasyGem) macht, können Sie das Programm nur mit [Ctrl]+[C] anhalten.
[Fortsetzen]
Dieser Button ist nur anwählbar, wenn ein Programm angehalten wurde.
Wenn Sie auf diesen Knopf klicken, wird die Programmausführung mit dem Befehl,
auf den das kleine Dreieck zeigt, wieder fortgesetzt.
[Eintreten]
Dieser Button ist nur anwählbar, wenn ein Programm angehalten wurde.
Wenn Sie auf diesen Knopf klicken, wird nur ein Befehl, nämlich der, auf den
das kleine Dreieck zeigt, ausgeführt. Handelt es sich dabei um einen Prozedur-
oder Funktionsaufruf, so springt der Programmzeiger in die Prozedur oder Funktion.
Gleiches gilt auch für GOSUB Befehle. Bei Funktionen
ist ausserdem zu beachten, dass diese auch in Formeln vorkommen können. In diesem
Fall wird in alle Funktionen eingetreten, die in der Formel vorkommen.
Wenn die Prozedur oder Funktion von einer Library zur Verfügung gestellt wird,
so tritt der Debugger nicht in das Unterprogramm ein. Dies wäre ja auch nicht
sinnvoll, da der Programmcode in der Library nicht gelistet wird und Sie dadurch
den Programmverlauf ohnehin nicht verfolgen könnten.
Hinweis: Einige Library-Befehle verwenden
Callback-Funktionen, die Sie selbst definieren müssen und die sich daher nicht
in der Library befinden (z.B. Uwin_Open aus der EasyGem
Library). Wenn Sie jetzt Library-Befehle mit Eintreten aufrufen, springt der Programmzeiger
zwar nicht in die Library, kann aber in Ihrer Callback-Routine landen, wenn diese
gerade von der Library aus aufgerufen wird.
Wenn Sie nicht gerade genau dieses beabsichtigen, sollten Sie besser den Button [Einzelschritt]
verwenden, um solche Verwirrungen zu vermeiden.
[Austreten]
Dieser Button ist nur anwählbar, wenn ein Programm angehalten wurde.
Er dient dazu, eine Prozedur oder Funktion zu verlassen, ohne vorher alle innerhalb
der Prozedur oder Funktion befindlichen Befehle in Einzelschritten auszuführen.
Genauer gesagt wird die Programmausführung fortgesetzt, bis der Debugger auf
ein RETURN, END_PROC, END_FN oder EXIT
stösst, das sich in der gleichen Hierarchieebene befindet, in der der Programmzeiger
war, als dieser Button angeklickt wurde.
Nach Anwahl dieses Knopfes steht der Programmzeiger also direkt hinter dem Befehl,
mit dem die Prozedur oder Funktion aufgerufen wurde. Entsprechendes gilt auch, wenn
Unterprogramme über GOSUB Befehle aufgerufen
werden.
Hinweis: Wenn Sie diesen Button benutzen, während sich der Programmzeiger nicht in einem Unterprogramm befindet, hat er die gleiche Wirkung wie [Fortsetzen] , da sich auf der obersten Hierarchieebene keine RETURN Befehle befinden.
[Einzelschritt]
Dieser Button ist nur anwählbar, wenn ein Programm angehalten wurde.
Die Funktion ähnelt der des Buttons [Eintreten], mit dem Unterschied, dass Unterprogrammaufrufe
immer wie BASIC-Befehle interpretiert werden, also niemals in Unterprogrammen angehalten
wird.
[Animation]
Dieser Button ist nur anwählbar, wenn ein Programm angehalten wurde.
Damit lässt sich eine Programmfortsetzung in Zeitlupe erreichen. In der Standardeinstellung
sorgt der Debugger dafür, dass maximal ein Befehl pro Sekunde ausgeführt
wird. Dieses Intervall lässt sich über die Dialogbox 'Debuggereinstellungen'
aber auch verändern.
[Beenden]
Dieser Button ist immer anwählbar. Mit ihm können Sie das vom Debugger
kontrollierte Programm jederzeit beenden. Damit schliesst sich auch automatisch das
Fenster für die Debuggersteuerung.
Achtung: Einige Omikron Basic Befehle warten
auf Eingaben des Benutzers, bevor das Programm fortgesetzt wird. Da der Debugger
ein Programm nur zwischen zwei Befehlen unterbrechen kann, nicht aber sozusagen mitten
auf einem Befehl, wird in diesen Fällen ein Debuggerkommando erst wirksam, wenn
der Befehl beendet wurde.
Im einzelnen sind dies die Omikron Basic Befehle INPUT,
LINE INPUT, FORM_ALERT und FILESELECT bzw.
FSEL INPUT sowie die EasyGem Befehle Easy_Alert,
Easy_Fsel, Easy_Fnav und Pick_Color.
Wenn sich Ihr Programm z.B. in einer INPUT Anweisung
befindet und Sie auf [Beenden] klicken, wird das Programm erst beendet, nachdem der
Anwender die Input-Anweisung mit [Return] verlassen hat.
Wenn Sie Ihr Programm über die Debuggersteuerung anhalten, ist es weitgehend vom Zufall abhängig, an welcher Stelle das Programm stoppt. Darum gibt es zwei weitere Möglichkeiten, ein Programm gezielt an einer bestimmten Stelle zu unterbrechen.
STOP Befehl
Noch bevor Sie Ihr Programm mit 'Debuggen' starten, fügen Sie einfach
einen STOP Befehl an der Stelle ein, an der das Programm
anhalten soll. Vielen, die früher mit BASIC-Interpretern gearbeitet haben, dürfte
diese Methode bekannt vorkommen. Der STOP Befehl
hält ein Programm an, ohne Variablen und Speicherinhalte zu löschen. Danach
können Sie mit der Debuggersteuerung das Programm
gezielt fortsetzen.
Achtung: Der STOP
Befehl funktioniert nur, wenn das Programm mit 'Debuggen' gestartet wurde.
Bei einem normal compilierten Programm führt der STOP
Befehl zu einer Fehlermeldung mit anschliessender Beendigung des Programms.
Breakpoints
Breakpoints sind zusätzliche Unterbrechungspunkte, die Sie in Ihr
Programm einfügen können. Im Unterschied zu STOP
Befehlen können Breakpoints erst gesetzt werden, nachdem das Programm
mit 'Debuggen' gestartet wurde. Toppen Sie dazu das Fenster mit dem Quellcode und
klicken Sie einfach bei gedrückter [Ctrl] Taste auf die Stelle im Quellcode,
an der ein Breakpoint gesetzt werden soll. Es erscheint eine kleine Ellipse in der
Farbe der Kommentarzeilen. Sobald nun der Programmzeiger Ihres Programms über
diese Stelle läuft, wird das Programm angehalten und Sie können wieder
mit der Debuggersteuerung eine gezielte Analyse vornehmen. Durch nochmaligen Klick
auf einen Breakpoint wird dieser wieder entfernt.
Sie können praktisch beliebig viele dieser Breakpoints setzen. Im Unterschied
zu STOP Befehlen sind Breakpoints nur während
einer Debuggingphase wirksam. Nach Beendigung des Programms werden Sie automatisch
gelöscht. Sie können auch nicht gespeichert oder auf das Clipboard kopiert
werden. Wenn Sie dauerhafte Breakpoints in Ihr Programm einbauen möchten, müssen
Sie dafür den STOP Befehl verwenden.
Hinweis: Nicht an jeder Stelle eines Programms kann man einen Breakpoint setzen, da z.B. Kommentarzeilen vom Compiler ausgelassen werden und einige BASIC-Befehle nur zur Strukturierung dienen, aber keinen Objektcode erzeugen. In diesen Fällen erscheint der Breakpoint an der nächsten möglichen Programmstelle vor der Position, auf die Sie geklickt haben.
Achtung: Wenn Sie die EasyGem Library verwenden
oder eine eigene Event-Handling Routine programmiert haben, kann Ihr Programm den
Inhalt von Fenstern nicht restaurieren, wenn es vom Debugger angehalten wurde.
Dies gilt nicht für Omikron Basic Ausgabefenster. Diese werden nämlich
von einem kleinen Assembler-Programm verwaltet, das auch dann weiterläuft, wenn
das BASIC Programm vom Debugger angehalten wurde.
Speicherfenster
Speicherfenster können Sie über den gleichnamigen Menüpunkt aus dem
'Programm' Menü öffnen. Mit Speicherfenstern können Sie sich den Inhalt
des RAM-Speichers ansehen.
In der linken oberen Ecke des Fensters befindet sich eine Eingabezeile, mit der Sie
festlegen können, ab welcher logischen Adresse der Speicherinhalt angezeigt
werden soll. Die Adresse können Sie mit einem Prefix davor in allen von Omikron
Basic unterstützten Zahlensystemen angeben (z.B. $A6553
oder 123456). Durch drücken von [Return] wird
der Speicherinhalt ab der angegebenen Adresse angezeigt.
Falls der angegebene Speicherbereich nicht existiert, erhalten Sie eine Fehlermeldung
und es wird nichts angezeigt.
Die Art der Anzeige können Sie über die Debuggereinstellungen
weitgehend beeinflussen.
Variablenfenster
In ein Variablenfenster können Sie die Namen von Variablen eingeben,
deren Inhalt dann angezeigt wird. Bei Stringvariablen wird zusätzlich dahinter
noch die Länge des Strings angegeben.
Für die Indizes von Feldvariablen dürfen dabei nur Konstanten oder Einzelvariablen
verwendet werden (z.B. A#(X,Y) oder A#(1,3)).
Solange ein Programm nicht mit 'Debuggen' gestartet wurde, ist der Inhalt von Variablen
natürlich 0 bzw. bei Strings der Leerstring.
Das Zahlensystem, in dem der Variableninhalt angezeigt werden soll, können Sie
durch ein Prefix festlegen. So würde z.B. die Eingabe $Tex$
den Inhalt des Strings Tex$ nicht als Zeichenkette,
sondern als Bytefolge in Hexzahlen ausgeben. Ähnlich ergäbe %A
den Inhalt der Variablen A als Binärzahl. Standardmässig
erfolgt die Ausgabe von numerischen Variablen immer als Dezimalzahl und von Strings
immer als Zeichenkette. Bei Strings kann man durch Voranstellen eines Nummernzeichens
"#" auch eine Ausgabe als dezimale Bytefolge
bewirken. Dies ist besonders interessant, wenn man sich für die ASCII-Werte
eines Strings interessiert.
In Variablenfenstern funktionieren auch Blockfunktionen. Statt die gewünschten
Variablen einzutippen, können Sie diese auch aus dem Programmfenster mit 'Kopieren'
und 'Einsetzen' in das Variablenfenster übertragen.
Ausserdem können Variablenfenster gespeichert, wieder geladen oder ausgedruckt
werden. Die Speicherung erfolgt dabei im ASCII-Fomat. Bei erneutem Laden werden die
Variablen dem gerade oben befindlichen Programmfenster zugeordnet.
Falls eine Variable nicht existiert oder ein Feldelement nicht im dimensionierten
Bereich liegt, wird die Zeile als Fehlerzeile (rot in der Standardeinstellung) markiert.
Ein Variablenfenster bezieht sich immer auf ein bestimmtes Programmfenster. Wird
dieses geschlossen, so werden automatisch auch alle damit verknüpften Variablenfenster
geschlossen, da die darin enthaltenen Variablen ja jetzt gar nicht mehr definiert
sind.
Auch für Variablenfenster lassen sich im Dialog Debuggereinstellungen
Änderungen vornehmen.
Debuggereinstellungen
Natürlich ist es auch möglich, alle wichtigen Funktionen des Debuggers
individuell zu konfigurieren. Dazu gibt es den Dialog 'Debuggereinstellungen', den
Sie aus der Dialogbox 'Editoreinstellungen' heraus aufrufen können. Die Dialogbox
kann während der Arbeit mit dem Debugger geöffnet bleiben, so dass Sie
z. B. während eines laufenden Animationsprozesses die Animationsgeschwindigkeit
ändern können.
Der Dialog ist unterteilt in die Bereiche Speicherfenster und Allgemein.
Speicherfenster:
In einem Speicherfenster können
Sie sich den Inhalt des RAM-Speichers anzeigen lassen. Dabei kann die Anzeige auf
unterschiedlichste Weise erfolgen.
Bytes pro Gruppe:
Mit diesem Popup-Menü legen Sie fest, wieviele Bytes nebeneinander dargestellt
werden, bis ein Leerzeichen eingefügt wird.
Bytes pro Zeile:
Dieser Wert gibt an, wieviele Bytes in einer Zeile angezeigt werden.
Adressen anzeigen in:
Hier können Sie wählen, ob die Speicheradresse, die links in einem Speicherfenster
angezeigt wird, als Dezimalzahl oder als Hexadezimalzahl dargestellt werden soll.
Bytes anzeigen in:
Dieses Popup-Menü ermöglicht es, für die Anzeige des Speicherinhalts
zwischen verschiedenen Zahlensystemen (von binär bis hexadezimal) zu wählen.
Zeichenkette anzeigen:
Da sich der Inhalt einer 8-Bit Speicherzelle immer auch als ein Zeichen mit dem entsprechenden
ASCII-Code interpretieren lässt, kann der Inhalt des Speichers auch als Folge
von ASCII-Zeichen interpretiert werden. Sinnvoll ist dieses im allgemeinen nur, wenn
sich an der untersuchten Speicherstelle auch tatsächlich Textstücke (z.B.
Inhalte von Stringvariablen) befinden. Ansonsten sieht man ein Schriftbild, das eher
an altägyptische Hieroglyphen erinnert als an den Inhalt eines Computerspeichers
;-)
Mit dieser Checkbox kann die zusätzliche Anzeige des Speichers als Zeichenkette
an- oder abgeschaltet werden.
Allgemein:
In diesem Bereich können weitere allgemeine Einstellungen der
Debuggerfunktionen vorgenommen werden.
Zeichen pro Zeile in Variablenfenstern:
Ebenso wie bei Programmfenstern kann auch bei Variablenfenstern
die Anzahl der Zeichen, die in einer Zeile maximal dargestellt werden können,
vom Benutzer eingestellt werden. Im allgemeinen reicht die Standardeinstellung von
255 Zeichen aus. Wenn Sie allerdings längere Strings im Variablenfenster verfolgen
möchten, kann es durchaus sinnvoll sein, diesen Wert zu erhöhen.
Verzögerung bei Animation [in msec]:
Der hier eingestellt Wert gibt an, wieviele Millisekunden der Debugger zwischen zwei
Befehlen wartet, wenn das Programm im Animationsmodus ausgeführt wird. Ein Wert
von 1000 bedeutet also, dass die Befehle im Sekundentakt ausgeführt werden.
Dabei wird die Ausführungszeit des Befehls selbst von der Verzögerungszeit
abgezogen. Wenn ein Befehl z.B. schon 0.3 s für die Ausführung benötigt,
wartet der Debugger nur noch 0.7 s, bis er den nächsten Befehl zur Ausführung
bringt.
Variablenfenster permanent aktualisieren:
Normalerweise wird der Inhalt von Variablenfenstern nur dann aktualisiert, wenn das
Programm in Einzelschritten oder im Animationsmodus ausgeführt wird. Mit dieser
Checkbox kann man nun festlegen, dass die Variablenfenster auch dann ständig
die aktuellen Variableninhalte anzeigen, wenn Ihr Programm normal abläuft.
Speicherfenster permanent aktualisieren:
Diese Checkbox bewirkt das gleiche wie die Vorherige, nur für Speicherfenster.
Bei Animation in PROCs und FNs eintreten:
Normalerweise werden Prozeduren und Funktionen im Animationsmodus wie BASIC-Befehle
behandelt. Mit dieser Checkbox kann bestimmt werden, dass in Prozeduren und Funktionen
hineingesprungen wird und die darin enthaltenen Einzelbefehle schrittweise ausgeführt
werden.
Am Ende der Dialogbox befinden sich drei Action-Knöpfe:
[Ausführen]
Die vorgenommenen Einstellungen werden ausgeführt und sind danach sofort
sichtbar bzw. wirksam. Sie können also z. B. während einer Animation die
Verzögerungszeit verändern und dann mit diesem Button aktivieren.
[Undo]
Die letzte mit Ausführen vorgenommene Veränderung wird rückgängig
gemacht.
[Abbrechen]
Die Dialogbox wird geschlossen, ohne dass die gemachten Einstellungen übernommen
werden.
Das Programm "Programmname" wurde unerwartet beendet.
In einigen Fällen kann es vorkommen, dass das zu debuggende Programm auf
unkontrollierte Weise spantan beendet wird. In diesen Fällen kann keine Nachricht
mehr an den Debugger geschickt werden, so dass dieser von dem Ende nichts erfährt.
Wenn Sie nun trotzdem versuchen, Debuggerbefehle auf das nicht mehr laufende Programm
anzuwenden, erhalten Sie diese Fehlermeldung.
Der adressierte Speicherbereich existiert nicht.
Diese Fehlermeldung erscheint, wenn Sie versuchen in einem Speicherfenster einen
Speicherbereich anzuzeigen, der gar nicht vorhanden ist.
Nachdem wir nun alle Komponenten des Debuggers beschrieben haben, wollen wir anhand
einiger Beispiele zeigen, wie man den Debugger benutzt. Die Beispielprogramme sind
mit Zeilennummern versehen, um besser auf bestimmte Zeilen Bezug nehmen zu können.
Für den Programmablauf sind die Zeilennummern nicht erforderlich. Alle Variablen
ohne Postfix sind vom Typ Long-Integer, wie es der Defaulteinstellung des Omikron
Basic Editors entspricht. Wenn Sie diese Einstellung verändert haben, müssen
Sie dies beim Übertragen des Programmcodes berücksichtigen.
Die hier aufgelisteten Beispielprogramme befinden sich auch im Ordner DEMO:Debugger
(Demo)
Beispiel 1:
Öffnen Sie jetzt ein neues Programmfenster und übertragen Sie das folgende Programm mit 'Kopieren' und 'Einsetzen' in das leere Programmfenster. In das Beispiel 1 haben wir einen Fehler eingebaut, den wir nun mit dem Debugger finden wollen.
|
Starten Sie das Programm zunächst mit 'Compilieren & Starten'. Das Programm soll die Primzahlen zwischen 11 und 120 berechnen, wobei angenommen wird, dass die Primzahlen < 11 schon bekannt sind. Wie Sie sehen, läuft das Programm normal und ohne irgendeine Fehlermeldung ab, rechnet aber falsch, denn die Zahl 49 wird als Primzahl markiert, obwohl sie durch 7 teilbar ist.
Beenden Sie das Programm und starten Sie es nochmal über den Menüpunkt
'Debuggen'. Das Programm stoppt jetzt in Zeile 35 und gibt die Fehlermeldung "Integer-Überlauf"
aus. Klicken Sie auf [OK]. Sie befinden sich jetzt im Debugger. Die Position, an
der das Programm angehalten wurde, ist durch ein kleines Dreieck markiert.
Um nun herauszufinden, worin der Fehler besteht, öffnen Sie ein neues Variablenfenster.
Geben Sie in das Fenster I, J und Primes(J)
ein, wobei Sie hinter jeder Eingabe [Return] drücken, so dass die Variablen
in verschiedenen Zeilen erscheinen. Wie Sie sehen, hat I
den Startwert 2, J
den Endwert 3 und Primes(J)=0,
so dass die Operation I MOD Primes(J) nicht definiert
ist und zu dem "Integer-Überlauf" führt.
Ein Blick auf Zeile 22 zeigt, dass in der READ Schleife
ein falscher Endwert für die Laufvariable J
angegeben ist (2 statt 3).
Klicken Sie nun auf [Beenden] in der Debuggersteuerung. Fügen Sie danach in
Zeile 18 einen STOP Befehl ein und korrigieren Sie
den falschen Endwert in Zeile 22 (2 in 3 ändern).
Danach starten Sie das Programm wieder mit 'Debuggen'. Das Programm wird jetzt direkt
hinter dem STOP Befehl angehalten. Im Variablenfenster
wird Primes(J) als Fehlerzeile dargestellt. Dies
liegt daran, dass dieses Feld noch nicht dimensioniert wurde. Gehen Sie jetzt in
Einzelschritten voran, indem Sie in der Debuggersteuerung auf [Einzelschr.] klicken.
Nachdem der DIM Befehl in Zeile 20 ausgeführt
wurde, wird Primes(J)=0 korrekt im Variablenfenster
angezeigt. Wenn Sie jetzt in Einzelschritten die READ
Schleife abarbeiten, können Sie im Variablenfenster verfolgen, wie die Primzahlen
nacheinander in das Feld Primes() eingelesen werden.
Am Ende der Schleife wird Primes(J) wieder als Fehler
dargestellt, da J jetzt 4 ist und Primes(J)
nur bis 3 dimensioniert wurde.
Wenn Sie in Zeile 25 angekommen sind, können Sie entscheiden, ob Sie die
Prozedur Display_Numbers mit [Einzelschr.] wie einen
Befehl ausführen wollen oder ob Sie mit [Eintreten] in die Prozedur hineinspringen
wollen. Um die Funktionen des Debuggers zu demonstrieren, entscheiden wir uns hier
für [Eintreten].
Da in der Prozedur Display_Numbers PRINT Ausgaben
in das Omikron Basic Ausgabefenster gemacht werden, sollten Sie das Programmfenster
so zur Seite schieben, dass Sie das Ausgabefenster sehen können.
Sie könnten jetzt natürlich in Einzelschritten alle Befehle in der Prozedur
einzeln ausführen, da hier aber nichts spektakuläres passiert, wollen wir
die Gelegenheit nutzen, eine weitere Funktion des Debuggers zu demonstrieren. Klicken
Sie dazu auf Animation. Der Debugger führt jetzt alle Befehle in Zeitlupe aus.
Dabei können Sie verfolgen, wie der Programmzeiger sich durch die beiden Schleifen
arbeitet und dabei die Zahlen in das Omikron Basic Ausgabefenster geschrieben werden.
Wenn Sie genug gesehen haben, klicken Sie auf [Anhalten]. Das Programm stoppt an
der aktuellen Stelle. Wenn Sie jetzt auf [Austreten] klicken, werden alle Befehle
innerhalb der Prozedur ausgeführt und das Programm erst wieder hinter dem Prozeduraufruf,
also in Zeile 26 angehalten.
Halten Sie jetzt die [Ctrl] Taste gedrückt und klicken Sie mit der Maus auf
das FOR in Zeile 31. Dadurch wird vor das FOR
ein Breakpoint gesetzt, der als Ellipse dargestellt wird. Klicken Sie jetzt auf [Fortsetzen].
Der Programmzeiger stoppt genau auf dem Breakpoint. Wenn Sie jetzt wiederholt auf
[Fortsetzen] klicken, können Sie verfolgen, wie jede einzelne Zahl daraufhin
untersucht wird, ob es sich um eine Primzahl handelt. Dabei können Sie im Variablenfenster
die Werte von I und der anderen Variablen verfolgen
und im Omikron Basic Ausgabefenster sehen, wie einzelne Zahlen als Nicht-Primzahlen
markiert werden.
Halten Sie jetzt wieder die [Ctrl] Taste gedrückt und klicken Sie auf den Breakpoint
in Zeile 31. Der Breakpoint wird wieder entfernt. Setzen Sie einen neuen Breakpoint
in Zeile 43 hinter das THEN. Klicken Sie danach auf
[Fortsetzen]. Das Programm stoppt jetzt immer dann, wenn eine neue Zeile begonnen
wird.
Entfernen Sie den Breakpoint wieder und klicken Sie auf [Fortsetzen]. Es werden jetzt
alle Nicht-Primzahlen markiert und das Programm befindet sich danach in der Warteschleife
in Zeile 45.
Klicken Sie jetzt auf [Anhalten]. Das Programm stoppt in der Warteschleife. Das funktioniert nur, weil in der Warteschleife ein EVENT Aufruf steht (COMPILER "EVENT" bzw. Easy_Mesag bei EasyGem Programmierung). Wenn sich Ihr Programm in einer Schleife befindet, in der keine EVENT Aufrufe gemacht werden, können Sie es aber immer noch mit [Ctrl] +[C] anhalten.
Klicken Sie jetzt auf [Beenden]. Eratosthenes wird beendet, die Debuggersteuerung verschwindet und Sie können den Quellcode wieder editieren, um z. B. weitere Primzahlen zu berechnen.
Beispiel 2:
Das zweite Beispiel enthält keinen Fehler und dient nur dazu, die Debuggerfunktionen weiter zu erläutern. Öffnen Sie zunächst wieder ein neues Programmfenster und übertragen Sie den Programmcode mit 'Kopieren' und 'Einsetzen' in das Fenster. Danach müssen Sie noch mit dem Menüpunkt 'LIBRARY zuladen' aus dem 'Bearbeiten' Menü die Extension Library zuladen.
|
Starten Sie das Programm jetzt mit 'Debuggen'. Wie zu erwarten stoppt es in Zeile
22, direkt hinter dem STOP Befehl. Gehen Sie nun
mit [Eintreten] voran, bis Sie in Zeile 58 angekommen sind. Öffnen Sie jetzt
ein neues Variablenfenster und geben Sie dort $Adr ein.
Nach Drücken der [Return] Taste wird die Adresse des in Zeile 57 angeforderten
Speicherblocks als Hexzahl im Variablenfenster angezeigt.
Öffnen Sie jetzt ein neues Speicherfenster und danach die Debuggereinstellungen
über 'Modus/Editoreinstellungen/Debugger'. Stellen Sie in dem sich öffnenden
Dialog 'Bytes pro Gruppe' auf 1, 'Bytes pro Zeile' auf 8, 'Bytes anzeigen in' auf
dezimal und 'Zeichenkette anzeigen' auf aus. Klicken Sie danach auf [Ausführen].
Der Inhalt des Speicherfensters wird jetzt in Form von 3-stelligen Dezimalzahlen
angezeigt. Die Anzeige als Zeichenkette verschwindet. Übertragen Sie jetzt den
Wert, der für Adr im Variablenfenster angezeigt
wird, mit 'Kopieren' und 'Einsetzen' in das Adressfeld des Speicherfensters und bestätigen
Sie mit [Return].
Wenn Sie jetzt in Einzelschritten weiter durch das Programm gehen, können Sie
im Speicherfenster verfolgen, wie die Zufallszahlen in den Speicher geschrieben werden.
Gehen Sie jetzt wieder in die Debuggereinstellungen und stellen Sie die 'Verzögerung
bei Animation' auf 100. Danach mit [Ausführen] bestätigen. Sorgen Sie dafür,
dass das Speicherfenster und das Fenster mit dem BASIC-Programm sichtbar sind und
klicken Sie dann auf [Animation] in der Debuggersteuerung. Sie können jetzt
beobachten, wie die Zufallszahlen im Zehntelsekundentakt in den Speicher geschrieben
werden.
Wenn Sie genug gesehen haben, klicken Sie auf [Anhalten] und danach auf [Austreten].
Damit verlassen Sie die Prozedur und befinden sich danach hinter dem Aufruf in Zeile
25.
Setzen Sie jetzt einen Breakpoint in Zeile 39, indem Sie bei gedrückter [Ctrl] Taste mit der Maus vor Set_Print_Size klicken und danach das Programm fortsetzen. Das Programm stoppt in Zeile 39. Klicken Sie jetzt auf [Eintreten]. Obwohl als nächstes eine Prozedur ausgeführt wird, springt der Programmzeiger in die nächste Zeile, weil sich die Prozedur Set_Print_Size in einer Library befindet.
Holen Sie jetzt das Omikron Basic Ausgabefenster nach oben. Klicken Sie danach auf [Animation]. Sie können jetzt verfolgen, wie die statistischen Daten ins Omikron Basic Ausgabefenster geschrieben werden.
Beispiel 3:
Bei diesem Beispiel handelt es sich um ein ganz einfaches Programm, mit dem man
aber leicht anzeigen kann, welche Werte von MOUSEBUT und INKEY$ zurückgegeben
werden, wenn man bestimmte Tasten drückt. Öffnen Sie zunächst wieder
ein neues Programmfenster und übertragen Sie den Programmcode mit 'Kopieren'
und 'Einsetzen' in das Fenster.
|
Gehen Sie in die Debuggereinstellungen und schalten Sie 'Variablenfenster permanent aktualisieren' an. Klicken Sie danach auf [Ausführen]. Öffnen Sie jetzt ein neues Variablenfenster und tragen Sie dort die Variablen %Mb und %Kbrd$ ein.
Starten Sie das Programm jetzt mit 'Debuggen'. Wenn Sie jetzt die Maustaste alleine oder in Verbindung mit irgendwelchen Modifier-Keys drücken, können Sie im Variablenfenster sofort verfolgen, welche Bits dabei gesetzt werden. Entsprechendes gilt für die normalen Tasten des Keyboards. Die dabei erzeugten ASCII-Codes, Virtual-Key-Codes und Modifier-Key-Codes werden in Kbrd$ angezeigt.
|
Support | Bestellen | Start | Home: http://www.berkhan.de |
|
© 1997-2001 |