Debugging: Fehler systematisch finden und beheben
Debugging bedeutet, die Ursache eines Programmfehlers gezielt zu finden, zu beheben und die Korrektur anschließend zu prüfen. Du suchst also nicht planlos im gesamten Code: Du reproduzierst den Fehler, grenzt ihn ein und vergleichst erwartetes mit tatsächlichem Verhalten.
Hake ab, was du schon kannst — und komm am Ende hierher zurück!
Testen zeigt den Fehler – Debugging erklärt ihn
Ein Bug ist ein Fehler, durch den ein Programm nicht wie vorgesehen arbeitet. Das sichtbare Problem ist jedoch nicht immer die eigentliche Ursache.
Testen
Beim Testen vergleichst du das beobachtete Ergebnis eines Programms mit dem erwarteten Ergebnis. Ein fehlgeschlagener Test zeigt, dass etwas nicht stimmt.
Debugging
Beim Debugging lokalisierst du den Fehler, erklärst seine Ursache, korrigierst ihn und prüfst die Korrektur. Debugging klärt also, warum der Test fehlschlägt.
Eine Anmeldung lässt ein gesperrtes Konto zu. Der Test zeigt das falsche Verhalten. Beim Debugging untersuchst du anschließend die geprüften Bedingungen und stellst fest, dass die Kontosperre in der Entscheidung nicht richtig berücksichtigt wird.
Testen entdeckt eine Abweichung. Debugging findet und beseitigt ihre Ursache. Beide Tätigkeiten gehören zusammen.
Drei wichtige Fehlerarten erkennen
Nicht jeder Fehler zeigt sich auf dieselbe Weise. Die Fehlerart liefert dir einen ersten Hinweis für die Suche.
| Fehlerart | Woran erkennst du sie? | Beispiel |
|---|---|---|
| Syntaxfehler | Der Code verletzt Schreibregeln der Programmiersprache und kann häufig nicht gestartet werden. | Eine schließende Klammer fehlt. |
| Laufzeitfehler | Der Fehler entsteht beim Start oder während der Ausführung. | Das Programm versucht, durch null zu teilen. |
| Logikfehler | Das Programm läuft, liefert aber ein unerwünschtes Ergebnis. | Eine falsche Bedingung gewährt Zugriff. |
Ein Logikfehler ist oft besonders schwer zu entdecken: Das Programm stürzt nicht unbedingt ab. Deshalb brauchst du Testfälle mit klaren Erwartungswerten.
In sechs Schritten von der Beobachtung zur Lösung
Ein belastbarer Debugging-Prozess besteht aus sechs Schritten:
- Fehler reproduzieren: Stelle die auslösenden Eingaben und Bedingungen möglichst genau nach.
- Fehler lokalisieren: Grenze den betroffenen Bereich mit Tests, Logs, Ausgaben oder einem Debugger ein.
- Ursache bestimmen: Suche die erste Stelle, an der der tatsächliche Zustand von der Erwartung abweicht.
- Fehler beheben: Ändere gezielt den ursächlichen Code.
- Korrektur validieren: Wiederhole den fehlgeschlagenen Test und prüfe weitere betroffene Funktionen.
- Vorgehen dokumentieren: Halte Ursache, Änderung und erfolgreiche Tests fest.
Eine Beschreibung wie „Die Anmeldung geht manchmal nicht“ reicht für eine genaue Diagnose selten aus. Notiere Eingaben, Programmzustand, Fehlermeldung und die Schritte bis zum Fehler. So wird aus einem vagen Problem ein reproduzierbarer Fall.
Die erste falsche Zustandsänderung finden
Beim Eingrenzen vergleichst du an mehreren Stellen den Soll-Zustand mit dem Ist-Zustand. Entscheidend ist nicht nur die Stelle, an der das falsche Ergebnis sichtbar wird. Suche die erste Stelle, an der ein Wert oder eine Entscheidung falsch wird.
Eine Anmeldefunktion soll nur dann wahr liefern, wenn das Passwort korrekt und das Konto nicht gesperrt ist.
Die fehlerhafte Bedingung lautet: passwort_korrekt oder nicht konto_gesperrt.
| Passwort korrekt? | Konto gesperrt? | Erwartet | Fehlerhafte Bedingung |
|---|---|---|---|
| ja | nein | wahr | wahr |
| ja | ja | falsch | wahr |
| nein | nein | falsch | wahr |
Beim ersten Fall bleibt der Bug verborgen. Die anderen Fälle zeigen, dass ein einziger günstiger Teil der Oder-Bedingung genügt. Die erste falsche Zustandsänderung entsteht deshalb bei der Auswertung dieser Bedingung.
Die gezielte Korrektur lautet: passwort_korrekt und nicht konto_gesperrt. Danach werden alle drei Fälle erneut getestet.
Mit verschiedenen Techniken kannst du solche Abweichungen sichtbar machen:
- Ein Haltepunkt stoppt das Programm an einer gewählten Stelle.
- Die schrittweise Ausführung führt jeweils die nächste Codezeile aus.
- Die Variableninspektion zeigt aktuelle Werte und Zustände.
- Print-Ausgaben und Logs protokollieren Werte und Programmabläufe.
- Beim Prinzip Teile und herrsche schließt du fehlerfreie Bereiche aus und verkleinerst den verdächtigen Abschnitt.
- Beim Backtracking verfolgst du den Ablauf vom sichtbaren Fehler rückwärts.
- Beim Rubber Duck Debugging erklärst du den Code Zeile für Zeile in einfachen Worten. Dabei können unklare Annahmen auffallen.
Mit Testfällen die Korrektur belegen
Eine Codeänderung allein beweist noch nicht, dass der Bug behoben ist. Wiederhole zuerst genau den Test, der den Fehler sichtbar gemacht hat. Prüfe danach weitere Fälle, damit die Korrektur keine neue Störung verursacht.
Für eine Funktion sind drei Arten von Testfällen besonders nützlich:
- Ein Normalfall prüft eine typische gültige Eingabe.
- Ein Randfall prüft einen Wert direkt an einer festgelegten Grenze.
- Ein ungültiger Fall prüft, wie das Programm mit einer nicht erlaubten Eingabe umgeht.
Für diese Übung gilt die Spezifikation: zugang_erlaubt(alter) akzeptiert ganze Zahlen von 0 bis 120. Ab 16 soll die Funktion wahr liefern. Andere Eingaben sollen abgewiesen werden.
| Testart | Eingabe | Erwartung |
|---|---|---|
| Normalfall | 20 | wahr |
| Randfall unter der Grenze | 15 | falsch |
| Randfall an der Grenze | 16 | wahr |
| Ungültiger Fall | sechzehn | Eingabe wird abgewiesen |
Die beiden Randfälle prüfen beide Seiten der entscheidenden Grenze. Nur 20 zu testen wäre zu schwach: Eine fehlerhafte Grenze könnte dabei unentdeckt bleiben.
Unit-Tests prüfen den geänderten kleinen Codebereich. Integrationstests prüfen sein Zusammenspiel mit einem Modul, Systemtests das Gesamtsystem. Regressionstests kontrollieren, ob die Änderung bisher funktionierende Bereiche beschädigt hat.
Wähle in jeder Lücke die passende Form und prüfe anschließend deine Antworten.
Beim Testen vergleichst du . Debugging sucht einer Abweichung. Nach der Korrektur prüfen , ob andere Funktionen weiterhin richtig arbeiten.
Karteikasten
Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.
Alles auf einen Blick
- Debugging
- Ausgangspunkt: Fehler reproduzieren
- Diagnose: Abweichung lokalisieren und Ursache bestimmen
- Beobachtung: Debugger, Print-Ausgaben und Logs nutzen
- Korrektur: ursächlichen Code gezielt ändern
- Nachweis: Wiederholungs- und Regressionstests ausführen
- Abschluss: Ursache, Änderung und Tests dokumentieren
Abschluss-Check
Du kannst erfolgreich debuggen, wenn du nicht beim sichtbaren Symptom stehen bleibst: Reproduziere den Fehler, finde die erste falsche Zustandsänderung, ändere die Ursache gezielt und belege die Korrektur mit passenden Tests.
Mit Google fortfahren