Zum Inhalt springen

FreeBasic: Debugging

Aus Wikibooks


Was ist Debugging

[Bearbeiten]

Viele von euch kennen sicher das Problem: Ihr habt ein Programm geschrieben; das Kompilieren hat geklappt, aber irgendwie macht das Programm nicht das, was es soll.

Hier werdet ihr erfahren, wie ihr Bugs (semantische Fehler) in eurem Programm finden könnt. Syntaxfehler (es kann nicht kompiliert werden) lasse ich weitgehend außen vor, da hier der Compiler meistens genau anzeigt, wo das Problem ist.


In QuickBasic gab es hübsche Möglichkeiten, das Programm mal anzuhalten, Variablen jederzeit abzufragen, usw. Dies war möglich, da QuickBasic einen Interpreter beinhaltete. FreeBasic hat (leider) nur einen Compiler, somit sind solche nützlichen Funktionen nicht möglich, zumindest nicht ohne externe Tools.

Es gibt also 3 Möglichkeiten, das Programm zu debuggen:

  1. Den Quellcode nach QB portieren (bzw. gleich in QB schreiben) und die genannten nützlichen Funktionen verwenden
  2. Ein externes Tool verwenden, wie Insight in Verbindung mit gdb
  3. Per Hand (zwar das Umständlichste, trotzdem das Beste für Anfänger)

In QuickBasic debuggen

[Bearbeiten]

Diese Methode lohnt sich nur bei kleinen Programmen, allerdings können sich beim Portieren neue Fehler einschleichen. Wenn einem das Debugging wichtig ist, und das Programm nicht gerade zeitkritisch ist und/oder Verbesserungen von FB braucht, empfehle ich das ganze Programm in QB zu scheiben.

Die wichtigsten Dinge sind:

  • Die STOP-Marken: Man kann sein Programm bis dahin laufen lassen und dann mit F8 in Einzelschritten jede Zeile ablaufen.
  • Mit F6 kommt man in eine Extra-Eingabefläche, wo man z. B. eine einzelne Funktion aufrufen oder 1-2 Codezeilen ausprobieren kann.
  • Variablen anzeigen: Damit kann man alle wichtigen Variablen (die man selber eingegeben hat) zu jeder Zeit sehen, aber natürlich nur, wenn das Programm angehalten ist. Wenn man in Einzelschritten vorwärts geht, werden auch die angezeigten Variablen aktualisiert.

Mit externen Tools debuggen

[Bearbeiten]

Es gibt nun eine Reihe von Programmen, mit denen man ausführbare Dateien, also die compilierten Exe-Dateien, überwachen kann. Mit den Programmen kann man den Speicher und Variablen überwachen und die Befehle Schritt für Schritt ablaufen lassen. Leider sind die meisten Programme nur mit Konsole zu bedienen, sie laufen selten unter Windowsumgebung. Also wohl nicht ganz das richtige für Anfänger. Auch mit dem komfortabelsten Programm Insight (http://prdownloads.sourceforge.net/dev-cpp/Insight_Binary.DevPak?download) habe ich so meine Probleme gehabt. Insight hat eine grafische Oberfläche und ein halbwegs vernünftiges Menü. Allerdings lief es bei mir sehr instabil, und ich habe es nicht geschafft, die Variablen während des Programmablaufs abzufragen; vielleicht lag es auch an mir. Wer es allerdings mit einem externen Tool versuchen will, kann ja Insight noch eine Chance geben. Eine andere Möglichkeit wäre noch GDB (http://www.gnu.org/software/gdb/download/), welches die Grundlage von Insight war, allerdings nur mit Konsole bedienbar ist.

Logfile

[Bearbeiten]

In Programmiersprachen wie C++ wird oft eine Logfile Klasse verwendet. Leider gibt es in FreeBasic (noch) keine Klassen. Logfiles sind trotzdem nützlich. Zum Glück kann man da Abhilfe schaffen. Hier ein paar Funktionen, mit denen ihr euer Programm im Fehlerfall debuggen könnt:

declare sub OpenLog()
declare sub WriteError(byval e as string)
declare sub WriteSuccess(byval s as string)
declare sub WriteInf(byval i as string)
declare sub WriteInt(byval n as string, byval i as integer)
declare sub CloseLog()

sub OpenLog()
    open "Logfile.htm" for output as #78    '78 darf von euch nicht mehr verwendet werden.
    print #78, "<html><body><h1>Logfile</h1>"
end sub

sub WriteError(byval e as string)
    print #78, "<span style="color:#ff0000;">" + e + </span><br />
end sub

sub WriteSuccess(byval s as string)
    print #78, "<span style="color:#00ff00;">" + s + </span><br />
end sub

sub WriteInf(byval i as string)
    print #78, "<span style="color:#00ffff;">" + i + </span><br />
end sub

sub WriteInt(byval n as string, byval i as integer)
    print #78, "<span style="color:#000000;">Die Variable " + n + " an der Adresse " + str(varptr(i)) + " hat den Wert " + str(i) + </span><br />
end sub

sub CloseLog()
    print #78, "</body></html>"
    close #78
end sub

Mit diesen Funktionen könnt ihr euren Quelltext an fehleranfälligen Stellen erweitern. Bei einem Programmabsturz habt ihr das Logfile, in dem bei richtiger Verwendung die Fehlerursache steht.

Per Hand debuggen

[Bearbeiten]

Wenn man per Hand Debugging betreibt, muss man sich selbst Überblick über die Variablen oder erreichten Zustände verschaffen. Dies geschieht, indem man sich die Variablen schon während des Programmablaufs anzeigen lässt, oder sich irgendwie anzeigen lässt, ob ein Zustand erreicht wird. Wenn eine Variable überprüft werden soll, setzt man einfach überall da, wo sie sich ändern kann (oder da, wo man einen Fehler vermutet), eine Variablenausgabe hin, z.B.

locate 1,1: print "Variable x an Stelle y"; x : sleep

Einfacher ist es, wenn man Makros zur Hilfe nimmt:

#define print_debug(variable)  Print "'" + #variable & "' hat in Zeile " & __LINE__ & " den Wert '" & variable & "'"

dim x As Integer
dim y As Single

x = 123
print_debug(x)

y= 1.222223
print_debug(y)

So muss man nur print_debug(variable) schreiben, was einiges an Code einspart.

Des öfteren passiert es auch mal, dass eine Bedingung bei If Then falsch ist oder Schleifen und SUBs erst gar nicht starten. Um dies zu überprüfen, kann man auch wieder

print "Schleife xyz hat gestartet"

wählen.

Dinge, die man beim Debuggen überprüfen/beachten sollte

[Bearbeiten]
  • Wo ändert sich die Variable von einem gültigen zu einem ungültigen Wert?
  • Prüfen, ob alle SUBs, Schleifen und IF-Bedingungen ordnungsgemäß ausgeführt oder durchlaufen werden!
  • Ist die Ausgabe korrekt?
  • Sind alle Variablen richtig deklariert? (In FB muss man viel mehr auf die Deklarierung achten als in QB und es sollte möglichst alles deklariert sein!)
  • Sind die angewendeten Funktionen überhaupt richtig?

Nur in sehr seltenen Fällen liegt der Fehler am Compiler (in FB aber wohl noch häufiger als in QB). Wenn man den Fehler halbwegs lokalisieren konnte, ihn aber nicht findet, hilft oft im Forum jemand.