Um der Sache auf den Grund zu gehen, sehen wir uns zunächst die Werte aller lokalen Variablen an mit ''info locals''. U.a. sehen wir, daß
I = 1 LL = -2147091208 L = 86Der Wert für LL ist merkwürdig, denn LL sollte von 1 bis N laufen, und mit ``print N'' überzeugen wir uns von
N = 100Um uns anzusehen, wann LL diesen seltsamen Wert bekommt, setzen wir einen ''Tracepoint'' an den ersten Befehl der LL-Schleife (Z.65), d.h. wir wollen jedesmal, wenn diese Stelle passiert wird, einige Informationen erhalten. Wir definieren dazu:
trace line 65 {echo/n "Zeile 65: LL = "; print LL; resume;}Damit werden jedesmal, wenn diese Stelle passiert wird, die Kommandos in den geschweiften Klammern ausgeführt, d.h. es wird - ohne anschließendes Newline - ein Text ausgegeben (echo/n), dann der Wert der Variablen LL angezeigt (print), und schließlich mit der Programm-Ausführung fortgefahren (resume). Ohne ''resume'' würde bei Erreichen des Tracepoint das Programm angehalten. Der Tracepoint wird durch ein Symbol im Source-Fenster angezeigt.
Wir starten das Programm nun neu mit dem Kommando ''run''. Da das Programm vom letzten Lauf noch aktiv ist, fragt CXdb nach, ob der entsprechende Prozeß abgebrochen werden soll. Wir antworten mit ''y'' für ja. Als Ergebnis des Trace erhalten wir:
Zeile 65: LL = (INTEGER*4) 1 Zeile 65: LL = (INTEGER*4) 2 Zeile 65: LL = (INTEGER*4) 3 Zeile 65: LL = (INTEGER*4) 4Danach erscheint wieder die alte Fehlermeldung. Daraus folgt, daß sich zwischen dem Tracepoint (Z.65) und dem Fehler (Z.69) der Wert von LL geändert hat, obwohl dort nur die Variablen DUM und A auftauchen. Wir sehen uns den Inhalt von A an mit ``print A''. CXdb gibt standardmäßig maximal 20 Werte eines Arrays auf einmal aus, in unserem Fall also nur den Anfang der ersten Zeile. Aber auch hier sieht man schon, daß darunter gigantisch große Zahlen sind, obwohl A am Anfang nur Zufallszahlen zwischen -1 und 1 enthalten soll. Mehrere Ursachen sind denkbar:
break routine LINALGNach ''run'' (und der üblichen Abfrage) bleibt das Programm in Zeile 46 von main.f , der ersten ausführbaren Zeile, stehen. Der Breakpoint wird im Source-Fenster durch ein ''B'' vor der Zeile angezeigt. Mit den Kommandos ''step'' und ''next'' kann man nun in Einzelschritten durch das Programm gehen, wobei ''next'' einen Unterprogramm-Aufruf als einen Schritt ansieht und komplett ausführt, während ''step'' in das Unterprogramm hineingeht. Mit zwei next-Schritten führen wir die Routine GETVEC aus und sehen uns mit ''print A'' die ersten 20 Werte von A an: Sie liegen alle im richtigen Bereich. Mit drei weiteren next-Kommandos gehen wir bis vor den Aufruf von GAUSSJ. Die Werte von A sind erwartungsgemäß unverändert. Nun gehen wir mit ''step'' in die Routine GAUSSJ hinein. ''print A'' zeigt, daß jetzt A falsche Werte hat, es wird also nicht richtig an GAUSSJ übergeben. Mit ''info args'' erhalten wir Informationen über die Argumente von GAUSSJ; insbesondere sehen wir, daß A hier den Typ hat, im Hauptprogramm aber als deklariert ist. Damit ist der erste Fehler gefunden: Die Argumente und Variablen in GAUSSJ sind nicht deklariert worden (die Routine wurde unverändert aus den ''Numerical Recipes'' übernommen).
PAUSE: SINGULAR MATRIXWir starten wieder den Debugger mit ''cxdb linalg'' und das Programm selbst mit ''run''. Das Proceß-Fenster erscheint mit der PAUSE-Zeile und einer Eingabe-Einforderung. Wir antworten aber nicht dort - das wurde den Prozeß beenden -, sondern im Command-Fenster mit ''Control-c'', um den Prozeß anzuhalten. Das Source-Fenster zeigt die augenblickliche Position an: Das Programm steht in GAUSSJ in Zeile 41. Um zu sehen, warum die IF-Abfrage in Z.40 erfüllt wurde, sehen wir uns mit ''info locals'' die entsprechenden Variablen an:
K = (INTEGER*4) 51 IPIV = INTEGER*4(1:50) 0x8004c040Der Fehler ist diesmal leicht zu finden: IPIV ist deklariert als 50-elementiges Feld, aber in Zeile 40 wird IPIV(51) abgefragt. Der Wert von K geht auf die Schleife in Z.33-43 zurück, in der K von 1 bis N=100 läuft. IPIV dagegen ist über den Parameter NMAX=50 deklariert.