next up previous
Nächste Seite: Hilfsprogramme zu M2Amiga Aufwärts: Der Debugger (m2debug) Vorherige Seite: Beispiele

Ein vollständiges Beispiel

Betrachten wir folgendes Beispielprogramm:

MODULE test;

FROM Heap IMPORT Allocate;

TYPE
 String = ARRAY [0..5] OF CHAR;
 NodePtr = POINTER TO Node;
 Node = RECORD
  next: NodePtr;
  id: LONGINT;
  data: String
 END;

VAR
 list: NodePtr;

PROCEDURE CopyString(in: ARRAY OF CHAR;
                     VAR out: ARRAY OF CHAR);
 VAR i: INTEGER;
 BEGIN
  FOR i:=0 TO HIGH(in) DO out[i]:=in[i] END;
  out[HIGH(in)+1]:=0C
 END CopyString;

PROCEDURE AddNode(id: LONGINT; s: ARRAY OF CHAR);
 VAR
  a: NodePtr;
 BEGIN
  a:=list;
  Allocate(list, SIZE(Node));
  list^.next:=a;
  list^.id:=id;
  CopyString(s, list^.data)
 END AddNode;

BEGIN
 list:=NIL;
 AddNode(4, "Hello");
 AddNode(3, "the");
 AddNode(1, "Computer");
 AddNode(2, "World")
END test.mod

Nachdem Sie das Programm übersetzt und gelinkt haben, starten sie es, indem Sie ,,test`` eingeben. Unmittelbar nach dem Start erscheint ein Requester mit der Fehlermeldung ,,Bereichsfehler (CHK)``. Wenn Sie zuvor den Hintergrundprozess m2debug bereits gestartet haben, oder dies in diesem Moment nachholen, haben Sie nun die Möglichkeit, unseren Debugger zu aktivieren. Wir wählen im Requester die Option debug, und auf einem neuen Screen erscheinen die fünf Fenster des Debuggers. Im Modulfenster sehen Sie die Liste der benutzten Moduln:

0   Arts     00215AA8
1   test     002067A8
2   Heap     00215B54
3   ExecL    00215B5C
4   DosL     00215B64

Der obige Ausschnitt zeigt, dass unser Programm test als Modul 1 geladen ist. Im Fenster ,,Aufrufkette`` wird die Fehlerursache und die Prozedur-Aufrufkette dargestellt:

-- Bereichsfehler (CHK)
CopyString    in test
AddNode       in test
test          in test

Wie wir in diesem Fenster sehen, ist ein Bereichsfehler -- hervorgrufen durch einen Prozessortrap der MC68000 Instruktion CHK -- in der Prozedur CopyString aufgetreten. Diese Prozedur wurde von der Prozedur AddNode aufgerufen, die wiederum vom Hauptprogramm test aufgerufen wurde. Da der Debugger die Referenzdatei des Moduls test gefunden hat, kann er alle Prozedurnamen ausschreiben. Sonst hätte der Debugger nur die Anfangsadresse der Prozedur ausgeben können.

Im Quelltext-Fenster sehen wir, wo genau der Fehler passierte. Die Zuweisung

out[i]:=in[i]

wird vom Debugger invertiert dargestellt. Die fehlerhafte Anweisung ist zunächst vertikal eingemittet; Sie können jedoch den Quelltext beliebig durchblättern. Der Zugriff auf das i-te Element des Feldes in oder out hat den Fehler verursacht.

Im Prozedur-Fenster können wir durch Anklicken einer Zeile mit der rechten Maustaste auch die Fehlerstelle in den anderen Prozeduren betrachten. Klicken wir die Zeile mit der Prozedur AddNode an, so erscheint im Fenster ,,Quelltext``, wiederum hervorgehoben:

CopyString(s, list.data)

Dies ist besonders nützlich, wenn eine Prozedur an mehreren Stellen aufgerufen wird. So ist nämlich die Umgebung der aufgerufenen Prozedur ersichtlich.

Im Daten-Fenster 1 erscheinen die lokalen Variablen der Prozedur CopyString

-- CopyString
-- Type = PROCEDURE
in       *    (dyn)  ARRAY
out      *    (dyn)  ARRAY
i                 6  INTEGER

Durch Anklicken der linken Maustaste auf in, erscheint folgende Ausgabe:

-- CopyString.in
-- Type = ARRAY (ARRAY [0..7] OF CHAR)
0        "C"  CHAR
1        "o"  CHAR
2        "m"  CHAR
3        "p"  CHAR
4        "u"  CHAR
5        "t"  CHAR
6        "e"  CHAR
7        "r"  CHAR

In der obersten Zeile finden wir den Namen der aktuellen Struktur. In unserem Falle ist dies die Variable in in der Prozedur CopyString. Sollen weitere Variablen in der Prozedur CopyString angeschaut werden, können wir in der obersten Zeile mit dem linken Mausknopf den Bezeichner CopyString anklicken. Dadurch kehren wir wieder in die vorangehende Umgebung zurück. Nun lassen wir uns noch die Variable out anzeigen.

-- CopyString.out
-- Type = ARRAY (ARRAY [0..5] OF CHAR)
0        "C"  CHAR
1        "o"  CHAR
2        "m"  CHAR
3        "p"  CHAR
4        "u"  CHAR
5        "t"  CHAR

Wir erkennen nun die Fehlerursache. Das Feld out umfasst nur 6 Elemente von 0 bis 5. Die Variable i hat den Wert 6, wie in der ursprünglichen Anzeige unschwer zu erkennen war. Somit führte die Zuweisung zum 7. Element zum Bereichsfehler.

Als weiteres Beispiel für das leistungsfähige Blättern in den Datenstrukturen folgen die möglichen Ausgaben, wenn die globale Zeigerkette list näher betrachtet werden soll. Von Anfang an sind im Daten-Fenster 2 alle modulglobalen Daten angezeigt: In diesem Fall ist dies nur die Variable list

-- test
-- Type = MODULE
list     * 00206440  NodePtr

Durch Anklicken des Bezeichners list wird der Inhalt angezeigt. Dieser besteht aus einem weiteren NodePtr, einem LONGINT und einer Zeichenkette.

-- test.list^
-- Type = Node (RECORD)
next     * 002063C8  NodePtr
id                1  LONGINT
data     *        6  String

Anklicken des Elementes next ermöglicht das weitere Entlangwandern der Zeigerliste. Dort sind logischerweise die gleichen Elemente vorhanden, diese sind jedoch mit anderen Werten gefüllt

-- test.list^.next^
-- Type = Node (RECORD)
next     * 002063B0  NodePtr
id                3  LONGINT
data     *        6  String

Wird das data Feld angeklickt, lässt sich der aktuelle Inhalt der Zeichenkette anschauen. Dabei ist der Inhalt der Elemente 4 und 5 nicht von Belang, da das Element 3 ein Nullzeichen (0C = ASCII.nul) enthält, womit die Zeichenkette logisch beendet ist.

-- test.list^.next^.data
-- Type = String (ARRAY [0..5] OF CHAR)
0    "t"  CHAR
1    "h"  CHAR
2    "e"  CHAR
3     0C  CHAR
4   233C  CHAR
5    "Z"  CHAR


next up previous
Nächste Seite: Hilfsprogramme zu M2Amiga Aufwärts: Der Debugger (m2debug) Vorherige Seite: Beispiele
Claudio Nieder 2000-11-12