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

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