"Fehler suchen"-Tutorial
Übersicht

![]() |
MidimasterBetreff: "Fehler suchen"-Tutorial |
![]() Antworten mit Zitat ![]() |
---|---|---|
"Fehler suchen"-Tutorial
Dieses Tutorial soll helfen Fehler in eigenen Programmen zu finden oder vor vorne herein zu vermeiden. Dabei werden Strategien erklärt, wie der Programmcode zeitsparend und systematisch abgesucht werden kann. Außerdem werden Empfehlungen gegeben, wie der Programmcode vorzubereiten ist, damit er in den Blitz-Foren von Dritten leicht gelesen werden kann. (Ich bitte alle, sich mit eigenen Einträgen rauszuhalten und dafür lieber den Thread "Kritik an Midimaster-Tutorials" zu nutzen. Dieses Tutorial soll den Anfänger möglichst durch keine Diskussionen irritieren.) Kritik hier hin: Kritik-Thread Allen Anfängern lege ich wärmstens ans Herz dieses Tutorial durchzuarbeiten. Es spart euch viele Fehler in späteren Programmen. Fragen von Hilfesuchenden bitte ins BB-Beginners-Corner (https://www.blitzforum.de/forum/viewforum.php?f=18), aber auf keinen Fall hier hin posten! Lektion I: Fehler vermeiden ![]() Lektion II: Wie anfangen? ![]() Lektion III: Code zerteilen ![]() Lektion IV: Fehlersuche ![]() Lektion V: weitere Tipps zur Fehlersuche ![]() |
||
- Zuletzt bearbeitet von Midimaster am Di, Mai 11, 2010 9:45, insgesamt 8-mal bearbeitet
![]() |
MidimasterBetreff: Fehler vermeiden |
![]() Antworten mit Zitat ![]() |
---|---|---|
Fehler vermeiden
Zunächst wird erklärt, wie der Code aussehen soll, damit möglichst wenig Fehler entstehen. Wenn schon ein Fehler entstanden ist, der sich einfach nicht finden lässt, sollte der Code nach diesen Regeln umgebaut werden, bevor die Fehlersuche beginnt. Einrücken des Quelltextes Rücke Deine Zeilen um einen weiteren Tab ein, wenn Dein Programm eine dieser Strukturen benutzt: Zitat: Repeat, For, If, Select, OpenFile, OpenStream, etc..
BlitzBasic: [AUSKLAPPEN] For I=1 To 100 Gewöhne dir beim Schreiben an, gleich das Ende der Struktur zu schreiben, bevor du dich dem Inhalt widmest: Schritt 1bis 3: BlitzBasic: [AUSKLAPPEN] For I=1 To 100BlitzBasic: [AUSKLAPPEN] For I=1 To 100BlitzBasic: [AUSKLAPPEN] For I=1 To 100 keine Monster-Zeilen Nicht alles, was erlaubt ist, ist auch immer sinnvoll. Vermeide Zeilen, in denen mehrere Befehle stehen. Sie bringen sowieso keinen Performance-Vorteil: (nicht nachmachen) Zitat: If StringWidth(Left$(t$,i))+x>=MouseX() Input_mark_x=i:Exit
So geht es richtig: BlitzBasic: [AUSKLAPPEN] If StringWidth(Left$(t$,i))+x>=MouseX() Then Nur wenn jeder Befehl eine eigene Zeile bekommt, können Dritte ihn schnell erfassen. Aber nicht nur Zeilen mit mehr Befehlen können zerlegt werden. Teile auch reine Code-Zeilen: (nicht nachmachen) Zitat: Rect StringWidth(Left$(t$,Input_mark_x))+x,y,StringWidth(Mid$(t$,Len(Left$(t$,Input_mark_x)+1),Input_mark_w)),FontHeight(),1
Alles klar? Man ahnt wohl, was hier gecodet wurde, aber würde man auch einen Fehler darin finden? So wäre es besser: BlitzBasic: [AUSKLAPPEN] VonX=StringWidth(Left$(t$,Input_mark_x)) So geht es richtig: BlitzBasic: [AUSKLAPPEN] Teil$ = Left$(t$, Input_mark_x) IF Logik und Lesbarkeit BlitzBasic: [AUSKLAPPEN] If KeyDown(203) And input_cursor_pos> m+v And msecs>Input_timer+100 lässt sich auch so schreiben: BlitzBasic: [AUSKLAPPEN] If KeyDown(203) Then Logische AND-Verknüpfungen lassen sich immer in mehrere Zeilen zerlegen. Von der Logik ist beides das Gleiche Zwei Dingen sind dabei wichtig: Gewöhne dir an immer das Then am Ende der Zeile zu schreiben. Setze Klammern, wenn eine der beiden Bedingungen mehr als ein Ausdruck ist: BlitzBasic: [AUSKLAPPEN] If ( (x+dx)<0 ) Or ( (x+dx)>1000 ) Then Hierbei bemerktst du dann oft schon im Vorfeld Deine Logikfehler Sinnvolle Funktions- und Variablennamen Bildschirm-Koordinaten werden mit X Y und Z beschrieben. Verwende also diese Zeichen nur, wenn es wirklich um Koordinaten geht. Eine Mauskoordinate könnte z.B. MausX heißen, die aktuelle Position PosX, ZSpeed für eine Geschwindigkeit in Z-Richtung, usw.... Kleine Zählvariablen, nur kurz benötigte Variablen heißen gerne i oder j. Verwende diese Namen deshalb nie für bedeutende Variablen im Programm. Einer, der den Code liest, könnte ihre Bedeutung übersehen. Bedeutende Variablen und Funktionen bekommen komplette Worte oder werden aus mehreren Wortteilen zusammengesetzt, wobei der Wortanfang immer groß geschrieben wird. Hier verweise ich jetzt einfach einmal auf mein Namens-Tutorial: https://www.blitzforum.de/foru...050#354014 |
||
- Zuletzt bearbeitet von Midimaster am Mo, Jan 11, 2010 12:32, insgesamt 3-mal bearbeitet
![]() |
MidimasterBetreff: Lektion II Wie anfangen? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wie anfangen?
Wenn du ein neues Projekt anfängst stehst du vor lauter unfertigen Einzel-Baustellen. Um das Programm zu testen, müssten sie eigentlich erst alle fertiggestellt sein. Doch bis zu diesem Zeitpunkt hast Du vielleicht bereits 10 Fehler im Code. Und die Suche nach den Fehlern wird zur Qual. Wir müssen also einen Weg finden, wie wir einzelne Teile bereits im Gesamtprogramm testen können, bevor die anderen Teile überhaupt geschrieben sind. Wie soll das möglich sein? Wir faken (von engl. "to fake"=schwindeln)! Diese Tutorial zeigt Dir, wie man nach wenigen Minuten das gesamte Programm bereits testen kann. Wir erklären das am Projekt "Dia-Show". Die Dia-Show soll ein beliebiges Verzeichnis an Bildern einlesen können, daraus eine Playlist erstellen die Bilder laden dann auf dem Bildschirm darstellen. Dazu brauchen wir zunächst diese drei Funktionen: VerzeichnisEinlesen() LadeBild() BildDarstellen() im Laufe des Projektes werden immer mehr Funktionen dazukommen. Aber wir werden jede Funktion zunächst "faken". BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Dieses Programm läuft bereits! Teste es. Hier ist der größte Fehler der Beginners: die würden jetzt noch mehr schreiben, bevor sie es das erste Mal testen. Unser Programm kann fast noch nichts: Starten, Leben, Ende. Aber das können wir schon einmal testen.... Wichtig dabei sind die PRINT-Anweisungen. Sie zeigen Dir, welche Funktionen wann aufgerufen werden. Richtige Bilder sehen wir noch nicht, aber wir erhalten stattdessen den Text "Zeige das Bild". Der fake besteht zunächst darin, die Funktionen völlig leer zu halten. Aber wir sehen jetzt schon zwei Fehler: es werden keine unterschiedlichen Bilder "gezeigt" und der Wechsel aus Laden und Anzeigen erfolgt in einem rasanten Tempo. Ein Timer wird nötig und wir wollen nicht immer das gleiche Bild "sehen": BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Um wirklich ein Bild darzustellen müssten wir es vorher geladen haben. Um es aber laden zu können, müssten wir jetzt auch wissen, wie die Datei heißt, das faken wir einfach. Wir sind jetzt an einem Punkt, an dem das Programm laufen würde. Sorge zunächst dafür, dass in dem Verzeichnis einige Bilde liegen, die IMAGEx.PNG heißen. "x" ist dabei eine laufende Nummer von 1 bis 9. Natürlich musst Du den Pfad in der Funktion LadeBild() an deine Gegebenheiten anpassen. BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Entferne die PRINT-Texte auf keinen Fall vor Fertigstellung des gesamten Projektes. Durch sie erfährst Du auch dann was abläuft, wenn einmal wegen eines Fehlers kein Bild gezeigt wird. Das Prinzip ist jetzt klar. Es wird also immer nur an einer Routine gebastelt, während die anderen Routinen 100% stabil "funktionieren". Wir fügen jetzt das VerzeichnisLesen() ein. Dazu wird eine Liste der Dateinamen als Array dimensioniert und dann mit den Namen der Dateien eines Verzeichnisses gefüllt: BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Du siehst: es ist wieder gefaked. wir lesen das Verzeichnis gar nicht wirklich ein. Wir schreiben Code in VerzeichnisEinlesen(), der eine gefakte Liste von Dateinamen erstellt. Irgendwann wirst Du diese Routine durch die Echte ersetzen. Aber schon jetzt kannst Du in den anderen Programmteilen weitere Features testen und Dich dabei 100% auf die Verzeichnis-Routine "verlassen". |
||
- Zuletzt bearbeitet von Midimaster am Mi, Dez 30, 2009 11:23, insgesamt 5-mal bearbeitet
![]() |
MidimasterBetreff: Lektion III: Den Quellcode gliedern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Den Quellcode gliedern
Teile Deinen Quellcode optisch ein, indem Du Leerzeilen einfügst. Der Code wird beim Speichern dadurch nicht länger und auch die Performance leidet nicht. Füge nach jedem zusammengehörenden Arbeitsschritt (meist 3 bis 5 Zeilen) solche Leerzeilen ein. Versuche, manche dieser Arbeitsabschnitte in einer Funktion auszulagern. Versuche es vor allem dann, wenn Du das Gefühl hast, zwei Code-Stellen sehen sich sehr ähnlich. Hier am Beispiel einer Anfrage aus dem Forum. Der User sucht den Fehler in dieser Funktion: Zitat: Function Input$(t$,x,y,size_x,size_y,cursor=False,mark_color=128,maxlength=999999,Lengthtype=0) ' ---------------------------------------Block I Input_key=GetKey() If KeyHit(82) input_key=48 If KeyHit(79) input_key=49 If KeyHit(80) input_key=50 If KeyHit(81) input_key=51 If KeyHit(75) input_key=52 If KeyHit(76) input_key=53 If KeyHit(77) input_key=54 If KeyHit(71) input_key=55 If KeyHit(72) input_key=56 If KeyHit(73) input_key=57 If KeyHit(181) input_key=47 If KeyHit(55) input_key=42 If KeyHit(74) input_key=45 If KeyHit(78) input_key=43 If KeyHit(83) input_key=44 If KeyHit(156) input_key=13 '-------------------------------------------------Block II If KeyDown(203) And input_cursor_pos>0 And msecs>Input_timer+100 input_cursor_pos=input_cursor_pos-1 Input_timer=msecs Input_key=0 EndIf If KeyDown(205) And input_cursor_pos<Len(t$) And msecs>Input_timer+100 input_cursor_pos=input_cursor_pos+1 Input_timer=msecs Input_key=0 EndIf If KeyDown(211) And msecs>input_timer+100 Input_timer=msecs Input_key=0 If Input_mark_x>-1 t$=Left$(t$,Input_mark_x)+Mid$(t$,Input_mark_w+input_mark_x+1) Else t$=Left$(t$,input_cursor_pos)+Mid$(t$,input_cursor_pos+2) EndIf Input_mark_x=-1 EndIf If KeyDown(14) And Input_cursor_pos>0 And msecs>Input_timer+100 Input_timer=msecs Input_key=0 If Input_mark_x>-1 t$=Left$(t$,Input_mark_x)+Mid$(t$,Input_mark_w+input_mark_x+1) Else t$=Left$(t$,input_cursor_pos-1)+Mid$(t$,input_cursor_pos+1) input_cursor_pos=input_cursor_pos-1 EndIf Input_mark_x=-1 EndIf If (KeyDown(29) Or KeyDown(157)) And KeyHit(47) input_key=0 tmp$=ReadClipboardText$() t$=Left$(t$,input_cursor_pos)+tmp$+Mid$(t$,input_cursor_pos+1) input_cursor_pos=input_cursor_pos+Len(tmp$) EndIf If KeyHit(207) input_cursor_pos=Len(t$):Input_key=0 If KeyHit(199) input_cursor_pos=0:Input_key=0 ; ------------------------------------------------------Block III If MouseHit(1) Input_mark_w=0 Input_mark_x=-1 For i=1 To Len(t$) If StringWidth(Left$(t$,i))+x>=MouseX() Input_mark_x=i:Exit Next Input_cursor_pos=i EndIf If MouseDown(1) And Input_mark_x>-1 If MouseX()>=x And MouseX()<=StringWidth(t$)+x If MouseY()>=y And MouseY()<=FontHeight()+y ; Maus in Textbereich For i=1 To Len(t$) If MouseX()<StringWidth(Left$(t$,i))+x Input_mark_w=Len(Mid$(t$,Input_mark_x,i-Input_mark_x)):Exit Next EndIf EndIf EndIf If Input_key>=32 ; Eingabe getätigt t$=Left$(t$,input_cursor_pos)+Chr$(Input_key)+Mid$(t$,input_cursor_pos+1) input_cursor_pos=input_cursor_pos+1 EndIf If Len(t$)>maxlength t$=Left$(t$,maxlength) If cursor If einf c_width=FontWidth() Else c_width=2 Rect x+StringWidth(Left$(t$,input_cursor_pos)),y-1,c_width,FontHeight()+2,1 EndIf If Input_mark_x>-1 Color mark_color,mark_color,mark_color Rect StringWidth(Left$(t$,Input_mark_x))+x,y,StringWidth(Mid$(t$,Len(Left$(t$,Input_mark_x)+1),Input_mark_w)),FontHeight(),1 EndIf Return t$ End Function Zunächst fällt auf, dass die Funktion zu lang ist. Zur besseren Übersicht habe ich ihn hier im Zitat Markierungen ("....Block II...") eingefügt. Es sind mehrere eigentlich völlig unabhängige Funktionalitäten enthalten: -Tastatur-Abfrage -Tastencode-Konvertierung -InputString-Erstellung und Manipulation -Maussteuerung -TextMarkierungsfunktion Jeder dieser Bereiche sollte nun in eine eigene Funktion: BlitzMax: [AUSKLAPPEN] Input_Key=GetInputKey() Eine Funktion sollte (wenn möglich) nicht größer als 50 Zeilen lang sein. Dies ist in etwa die Menge an Zeilen, die auf eine Bildschirmseite passt. Unser Code wurde durch diese Aktion nicht kürzer, aber ein "unkritischer" Teil des Codes wurde so optisch entfernt. Jetzt zum zweiten Block Dieser Block war ursprünglich 40 Zeilen lang und wenig übersichtlich. Es werden bei jedem Durchgang alle IF-Abfragen jedes Mal abgefragt. Dabei schließen sie sich gegenseitig aus. Der User drückt meist nur 1 Taste gleichzeitig. Einige der Abfragen waren auch von einem Timer abhängig. Sie wurden zu einem Block zusammengefasst: BlitzBasic: [AUSKLAPPEN] If msec > (Input_Timer +100) Was hier noch auffällt ist die Häufung von Stringsschneide-Aktionen. Ich werfe sie in eine eigene Funktion: BlitzBasic: [AUSKLAPPEN] Function CutString$(locString$,Bis%,Ab%) Im Rest erlaube ich mir wegen der Lesbarkeit alle Namen wie input_cursor_pos% durch kürzere wie Cursor% zu ersetzen. Dies ist möglich, weil ich am Anfang der Funktion... Zitat: Cursor=input_cursor_pos
...schreibe und am Ende...
MarkerX=Input_mark_x Zitat: input_cursor_pos=Cursor
Input_mark_x=MarkerX Danach sieht Block II jetzt so aus: BlitzBasic: [AUSKLAPPEN] Function ChangeInput$(t$) Der dritte Teil dient als Routine zum Zeichnen eines Markierungsblocks. Er wird natürlich ebenfalls in eine eigene Funktion gepackt und im Hauptprogramm nur aufgerufen: BlitzBasic: [AUSKLAPPEN] Function TextMarkieren(t$) Die ursprüngliche Hauptfunktion ist nun übersichtlich geworden: BlitzBasic: [AUSKLAPPEN] Function Input$(t$,x,y,size_x,size_y,cursor=False,mark_color=128) Der Code hier funktioniert übrigens nicht, er ist nur symbolisch zu verstehen. Die Fehler des Users sind nicht verbessert und es wurde auch noch nicht über das LOCAL-machen der Funktionsparameter nachgedacht (Kapselung der Funktionen) |
||
- Zuletzt bearbeitet von Midimaster am Mi, Dez 30, 2009 11:52, insgesamt einmal bearbeitet
![]() |
MidimasterBetreff: Lektion IV: Fehlersuche |
![]() Antworten mit Zitat ![]() |
---|---|---|
Lektion IV: Fehlersuche
Der erste und wichtigste Schritt bei der Fehlersuche sind kurze Code-Zeilen. Dadurch kannst du den Fehler schneller einkreisen und einer bestimmten Aktion zuordnen. Sollte Dein Code diesen Grundsatz noch nicht erfüllen, so lies Lektion I. Der zweite Schritt ist, sich auf bereits 100% Funktionierendes verlassen zu können. Sollte Dein Code hier nicht sicher sein, so handle das nächste Mal nach Lektion II und III. Traue keiner einzigen Deiner Code-Zeilen! Der Hauptgrund, warum du einen Fehler nicht findest, ist immer, weil man an der Stelle sucht, wo man seine Auswirkungen im Programm bemerkt hat. Dazu ein fehlerhaftes Beispiel: BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Der User startet das Programm und das Bild wird nicht angezeigt. Der Fehler ist so offensichtlich, weil es ja ein Beispiel sein soll!!! Uns soll es jetzt mehr um die Strategie gehen, wie man diesen Fehler entdecken könnte. DrawImage erzeugt einen RuntimeError, wenn es versucht ein Bild anzuzeigen, das nicht geladen werden konnte. Dies passiert bei diesem Fehler aber nicht. Also glaubt der User er hätte einen Blitz-Bug entdeckt. Er fragt im Forum nach, ohne auf die Idee gekommen zu sein, ob überhaupt das Programm läuft oder überhaupt irgendetwas angezeigt wird. PRINT und DEBUGLOG sind Deine Freunde! Verwende bei jeder Funktion, die Du aufrufst, bei jeder Struktur (IF, REPEAT, FOR, etc...), die du betrittst immer einen PRINT-Befehl, um zu überprüfen, ob du diesen Abschnitt überhaupt betreten hast. Die Ausgabe solcher PRINTS erfolgt in das DEBUG-Fenster. Ein zweites Fenster neben Deinem Spiel, in dem du den Programm-Ablauf verfolgen kannst. Im Menü über "Program -> Debug Enabled?" kann man den Debugger einschalten. Im Falle eines Fehlers stoppt das Programm und ermöglicht dir alle bis dahin ausgegebenen PRINTs durchzulesen. Auch du kannst das Programm an jeder Stelle durch ein einfaches Waitkey() anhalten und so das DEBUG-Fenster lesen. Diese Befehle bleiben im Programm, bis das Projekt beendet ist. Selbst danach kannst su sie ausmarkieren, statt sie zu löschen, dann dienen sie immer noch als Kommentare. Ob su PRINT oder DEBUGLOG verwendest, hängt von deiner BlitzBasic-Version ab. In den Beispielen schreibe ich jetzt immer DEBUGLOG BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Beobachte immer genau was su erlebst. Ein ungeübter User wird sagen, dass er sein Bild nicht sieht. Ein geübter User wird das ganze größer fassen und sagen: "Eigentlich sehe ich gar nichts!". Wenn auf dem Monitor noch gar nichts zu sehen war, wäre es klug zu testen, ob den überhaupt etwas angezeigt wird. Wir fügen daher gleich nach Graphics eine Zeile BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Natürlich fehlte der FLIP. Der User ergänzt ihn und stellt fest, das Rechteck wird gemalt, das Bild aber weiterhin nicht. Doch die DEBUGLOGs geben noch mehr Auskunft: Zitat: DEBUGLOG:
Programm startet Repeat Schleife Repeat Schleife Repeat Schleife .... Zwar sieht man ständig den Satz "Repeat Schleife" , aber es kommt nie zum " Taste F" , auch wenn ich die <F>-Taste drücke. Ergebnis der Recherche: Es kommt nie zum Sprung in die IF-Struktur. Angenommen wir erkennen nicht, warum das so sein kann, dann fügen wir einfach einen weiteren DEBUGLOG ein, der uns die Argumente, die in IF-Abfrage vorkommem, anzeigt: BlitzBasic: [AUSKLAPPEN] Graphics 800,600 Zitat: DEBUGLOG:
Programm startet Repeat Schleife Repeat Schleife Repeat Schleife gedrückt wurde f Repeat Schleife .... Jetzt ist klar, dass es am Buchstaben "F" lag. Die GetKey() liefert uns eine klein geschriebenes "f" zurück. Wir ändern das und erhalten prompt einen RuntimeError. Jetzt wird wieder das Blitzforum kontaktiert mit der Behauptung: "Wenn ich If A="f" Then schreibe, meldet BlitzBasic einen RuntimeError. Zitat: DEBUGLOG:
Programm startet Repeat Schleife Repeat Schleife Repeat Schleife gedrückt wurde f IF betreten Da wir aber das DEBUGLOG genauer ansehen, können wir erkennen, das die Zeile " IF betreten" noch ausgeführt wurde. Erst danach muss es zu Problemen gekommen sein. Wir fügen weitere DEBUGLOG ein und stellen fest, direkt beim DRAWIMAGE beendet sich unser Programm. Dort muss der Fehler liegen: BlitzBasic: [AUSKLAPPEN] ... Anmerkung: stelle für die weiteren Tests sicher, dass sich wirklich ein Testbild DEMOBILD.PNG in dem Verzeichnis "C:\test" befindet. Durch das Laden des Bildes wird die Variable BILD zu einem Pointer oder Handle. Das ist ein Zeiger auf den Speicher mit den Bildinformationen. Wenn das Laden gelungen wäre, dann hätte sie einen Wert größer Null. BlitzBasic: [AUSKLAPPEN] ... Aha, bei uns ist er 0, also ist das Laden schief gelaufen. Das kann nur am Dateinamen... Zitat: "C:\test\demobild.pmg"
...liegen. Wir entdecken das M in PMG und ändern es in PNG. Endlich! Jetzt wird es laufen, oder? Aber wieder ein RuntimeError. Jetzt nicht verzweifeln, sonder in das DEBUGLOG schauen. Das selbe Ergebnis wie vorhin: Bild ist immer noch 0. Zitat: DEBUGLOG:
Programm startet Repeat Schleife Repeat Schleife Repeat Schleife gedrückt wurde f IF betreten Bis hierher geht es Handle=0 Der Fehler muss also beim Laden sein. Was laden wir? "C:\test\demobild.png" ? Nein!!! Wir laden Datei! Also, kurz mal Datei überprüfen: BlitzBasic: [AUSKLAPPEN] ... und so sieht das DebugLog aus: Zitat: DEBUGLOG:
Programm startet Repeat Schleife Repeat Schleife Repeat Schleife gedrückt wurde f IF betreten Wir laden 0 Bis hierher geht es Handle=0 Also das hätten wir ja nun wirklich nicht erwartet. Einen Textstring hätten wir ja noch verstanden, aber eine Zahl? Datei soll doch den String aufnehmen, äh?? Schei... Datei$= !!! Noch einmal mein Satz vom Anfang, und jetzt stimmst du vielleicht zu: Traue keiner einzigen Deiner Code-Zeilen! Immer schön nachprüfen und DEBUGLOGs anlegen. Oder hättest du am Anfang dieser Lektion gedacht, dass der Code nicht einen sondern 4 Fehler enthält? |
||
![]() |
MidimasterBetreff: Lektion V: Weitere Tipps und Tricks zur Fehlersuche.... |
![]() Antworten mit Zitat ![]() |
---|---|---|
Weitere Tipps und Tricks zur Fehlersuche
Alles geht so schnell.... Ein Hauptproblem beim Finden von Fehlern ist die Geschwindigkeit mit der Programme heutzutage ablaufen. Hier wäre es gut, wenn man eine Speed-Bremse einbauen könnte, oder im Ernstfall das Programm bis zum Stillstand bringt. Daher dieser Tipp: baue folgende Zeilen in die REPEAT/UNTIL-Schliefe ein und lasse sie dort bis zur Fertigstellung des Projektes: BlitzBasic: [AUSKLAPPEN] If KeyHit(2) ;wenn Taste "1" gedrückt wird Stoppen So kannst Du das Programm um die Kritische Stelle abbremsen, bzw sogar komplett anhalten um einen Wert in der DEBUGLOG in Ruhe auszulesen. Uhrzeit mitanzeigen Oft glauben User, dass eine bestimmte Funktion nur ganz selten aufgerufen wird. Im DEBUGLOG scheint die dafür gesetzte Hinweiszeile auch gelegentlich zu kommen. BlitzBasic: [AUSKLAPPEN] Hinweis: Da im Code vergessen wurde, die Variable Gegner% GLOBAL zu definieren, ist sie jedesmals wieder 0, wenn die Funktion aufgerufen wird. Folge: Es werden zu viele Punkte vergeben. Da im Debugger nur die letzten 3 Zeilen zu sehen sind, steht dort ziemlich statisch 3x der Hinweis Zitat: neuer Gegner
Erst durch das Hinzufügen einer Zeitanzeige merkt der User, dass die Funktion viel zu oft gerufen wird: BlitzBasic: [AUSKLAPPEN] DebugLog MilliSecs() + " neuer Gegner" Beim Berechnen enstehen INTEGER-Werte Eine Hauptursache für Fehler, die hier im Forum gemeldet werden ist die Tatsache, dass der Autor sich nicht genügend Gedanken über den Variablen-Typ macht. Er überlässt BB diese Definition und wundert sich dann, warum ganz bestimmte Zustände nicht eintreten. Ganz typisch dieses Beispiel: BlitzBasic: [AUSKLAPPEN] SpielerX=400 Natürlich ist es hier ein sehr offensichtliches Beispiel. Aber tatsächlich geschieht dies bei den meisten Programmen dutzendfach: Durch die Festsetzung der Startkoordinate auf die Bildschirmmitte, wird die Variable SpielerX zu einer INTEGER gemacht. 400 ist ja eine INTEGER-ZAHL. Später wird aber nur noch sin() dazugezählt, und der ist immer eine Nachkommazahl unter 1. Folge: Die Summe wird immer wieder auf 400 gerundet! Die richtige Lösung lautet: BlitzBasic: [AUSKLAPPEN] Global SpielerX#=400 Generell SOLL jede Variable in Geltungsbereich und Typ vom Autor festgelegt werden! Gewöhne es dir an! weitere Tipps werden folgen.... |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group