Programmfehler oder Softwarefehler oder Software-Anomalie, häufig auch Bug () genannt, sind Begriffe aus der Softwaretechnik, mit denen für Software-Systemkomponenten Abweichungen zu einem geforderten oder gewünschten Sollzustand bezeichnet werden. Diese können auftreten, wenn z. B. eine bestimmte Festlegung der Spezifikation fehlerhaft ist oder falsch umgesetzt wurde („Fehlhandlung“), und führen zunächst zu einem internen „Fehlerzustand“ im Programm, der wiederum während der Programmausführung zu einem unerwarteten Verhalten oder Ergebnis führt oder führen kann („Fehlerwirkung“).
Zur möglichst vollständigen Erkennung und Behebung von Programmfehlern wird üblicherweise in den Prozessen der Softwareentwicklung, d. h. vor dem tatsächlichen, „produktiven“ Einsatz von Software, die Projektphase „Softwaretest“ durchlaufen, wobei eine Validierung durchgeführt wird. Dabei auftretende Fehler sind üblich und sie zu finden ist Ziel des Testens, während Fehler im laufenden Betrieb je nach Fehlerwirkung u. U. kritische Anomalien/Störungen darstellen. In der Praxis treten Computerprogramme ohne Programmfehler selten auf. Als Qualitätsmerkmal für Programme kennt man u. a. die Fehlerdichte. Sie bezeichnet die Anzahl an Fehlern pro 1.000 Zeilen Code (Kilo Source Lines of Code) bzw. je Function Point.
Als spezielle Instrumente zur Suche nach den Ursachen für Fehler in Programmen sind sogenannte Debugger hilfreich, mit denen ein Programm Schritt für Schritt ausgeführt und kontrolliert werden kann. Bei besonders kritischer Software (z. B. Flugzeugsteuerung) wird mitunter eine (aufwendige) formale Verifikation durchgeführt.
Zur Erfassung und Dokumentation werden sogenannte Bugtracker (wie Bugzilla oder Mantis) eingesetzt. Diese nehmen sowohl Fehlerberichte als auch Verbesserungsvorschläge und Wünsche (sog. ) der Nutzer oder allgemeine Vorgänge auf. Siehe auch Fehlermanagement.
Der Vorgang des Beseitigens eines Programmfehlers wird umgangssprachlich Bugfixing genannt. Das Ergebnis der Verbesserung wird in der Fachsprache als Bugfix, Patch oder Softwarepatch bezeichnet.
Definitionen
Ein Programm- oder Softwarefehler ist, angelehnt an die allgemeine Definition für „Fehler“ „Nichterfüllung einer Anforderung“. Konkret definiert sich der Fehler danach als „Abweichung des IST (beobachtete, ermittelte, berechnete Zustände oder Vorgänge) vom SOLL (festgelegte, korrekte Zustände und Vorgänge), wenn sie die vordefinierte Toleranzgrenze [die auch 0 sein kann] überschreitet.“
Nach ISTQBSpillner et al. Praxiswissen Softwaretest - Testmanagement (PDF) dpunkt.de bildet sich der Begriff 'Fehler' aus den folgenden Zusammenhängen: eine Fehlhandlung (englisch Error) „die menschliche Handlung, die zu einem Fehlerzustand führt ([nach IEEE 610])“ … führt zu einem Fehlerzustand (engl. Defect) „Defekt (innerer Fehlerzustand) in einer Komponente oder einem System, der eine geforderte Funktion des Produktes beeinträchtigen kann …“ der eine Fehlerwirkung (engl. Failure) nach sich ziehen kann „Die Manifestierung eines inneren Fehlers bei der Ausführung [des Programms] als ein inkorrektes Verhalten oder Resultat bzw. als Versagen des Systems.“ Beispiel Division durch null: Fehlhandlung: Null als möglicher Divisor wurde nicht geprüft/ausgeschlossen; Fehlerzustand: Das Programm ist (ggf. unbemerkt) fehlerhaft; Fehlerwirkung: Bei Auftreten eines Nullwerts als Divisor tritt während der Ausführung des Befehls ein Laufzeitfehler auf.
Als Synonym für „Fehler“ oder ergänzend dazu sind auch Ausdrücke wie Problem, Defekt, Abweichung, Anomalie, Mangel gebräuchlich. Damit kann die „Fehlerschwere“ auch begrifflich unterschieden werden, z. B. die Verletzung von Vorschriften zum Programmierstil, die Lieferung falscher Ergebnisse oder ein Programmabbruch.
„Bug“ als Synonym für Programmfehler mini|Logbuch-Seite des Mark II Aiken Relay Calculator mit dem ersten bug (1947) Das Wort bug bedeutet im Englischen „Schnabelkerf; Wanze“ und umgangssprachlich „landlebender Gliederfüßer“ oder „(insektenartiges) Ungeziefer“.Merriam-Webster Unabridged Dictionary (iOS-App, 2016): bug: a) an insect or other creeping or crawling invertebrate … b) any of certain insects commonly considered especially obnoxious … c) an insect of the order Hemiptera, especially: a member of the suborder Heteroptera … Im Jargon amerikanischer Ingenieure ist seit dem späten 19. Jahrhundert die Bedeutung „Fehlfunktion“ oder auch „Konstruktionsfehler“ bezeugt; diesem Wortgebrauch liegt die (scherzhafte) Vorstellung zugrunde, dass sich kleines Krabbelvieh am Getriebe, der Leitung usw. zu schaffen macht. Die ältesten Belege sind zwei Briefe Thomas Edisons aus dem Jahr 1878 an William Orton, den Präsidenten der Telegraphiegesellschaft Western Union, bzw. Tivadar Puskás, den Erfinder der Telefonzentrale, in denen es heißt:
sowie
Edison ist zwar nicht Erfinder, aber immerhin Kronzeuge für eine schon damals kursierende Bedeutung des Wortes. Die Verknüpfung des Begriffs mit Computern geht möglicherweise auf die Computerpionierin Grace Hopper zurück. Sie verbreitete die Geschichte, dass am 9. September 1945 eine Motte in einem Relais des Computers Mark II Aiken Relay Calculator zu einer Fehlfunktion führte. Die Motte wurde entfernt, in das Logbuch geklebt und mit folgender Notiz versehen: . Die Legende der Begriffsfindung hält sich hartnäckig, obwohl die Logbuch-Eintragung gerade darauf verweist, dass der Begriff schon zuvor gängig war. Zudem irrte Grace Hopper sich hinsichtlich des Jahres: Der Vorfall ereignete sich tatsächlich am 9. September 1947. Die entsprechende Seite des Logbuchs wurde bis Anfang der 1990er Jahre am Naval Surface Warfare Center Computer Museum der US-Marine in Dahlgren, Virginia, aufbewahrt. Zurzeit befindet sich diese Logbuchseite mit der Motte am Smithsonian Institute.Fred R. Shapiro: Etymology of the Computer Bug: History and Folklore. In: American Speech. Band 62, Nr. 4, 1987, S. 376–378.
Arten von Programmfehlern
In der Softwaretechnik (siehe auch) wird zwischen folgenden Typen von Fehlern in Programmen unterschieden:
Lexikalische Fehler sind nicht interpretierbare Zeichenketten, also undefinierte Bezeichner (Variablen, Funktionen, Literale...) Syntaxfehler sind Verstöße gegen die grammatischen Regeln der benutzten Programmiersprache, zum Beispiel die falsche Verwendung reservierter Symbole (z. B. fehlende Klammern), Typkonflikte, falsche Anzahl Parameter.
Lexikalische und Syntaxfehler verhindern in der Regel die Kompilierung des fehlerhaften Programms und werden daher frühzeitig erkannt. Bei Programmiersprachen, die sequentiell interpretiert werden, bricht das Programm üblicherweise erst an der syntaktisch/lexikalisch fehlerhaften Stelle ab.
Semantische Fehler sind Fehler, in denen eine programmierte Anweisung zwar syntaktisch fehlerfrei, aber inhaltlich trotzdem fehlerhaft ist, zum Beispiel Verwechslung des Befehlscodes, syntaktisch nicht erkennbare falsche Parameterreihenfolge. Logische Fehler bestehen in einem im Detail falschen Problemlösungsansatz, beispielsweise auf Grund eines Fehlschlusses, einer falsch interpretierten Spezifikation oder einfach eines Versehens oder Schreibfehlers. Beispiele: plus statt minus, kleiner statt kleiner/gleich usw. Die Toleranz gegenüber solchen Fehlern und die diese einschränken sollende Attributgrammatik von Programmiersprachen, wie etwa bei der Zuweisungskompatibilität von Datentypen, sind je nach verwendeter Programmiersprache sehr unterschiedlich ausgeprägt und können schwierig zu überschauende Sicherheitslücken und Programmabstürze verursachen. Designfehler sind Fehler im Grundkonzept, entweder bei der Definition der Anforderungen an die Software, oder bei der Entwicklung des Softwaredesigns, auf dessen Grundlage das Programm entwickelt wird. Fehler bei der Anforderungsdefinition beruhen oft auf mangelnder Kenntnis des Fachgebietes, für das die Software geschrieben wird oder auf Missverständnissen zwischen Nutzern und Entwicklern. Fehler direkt im Softwaredesign hingegen sind oft auf mangelnde Erfahrung der Softwareentwickler, unstrukturierte Programmierung oder auf Folgefehler durch Fehler in der Anforderungsspezifikation zurückzuführen. In anderen Fällen ist das Design historisch gewachsen und wird mit der Zeit unübersichtlich, was wiederum zu Designfehlern bei Weiterentwicklungen des Programms führen kann. Oftmals wird ohne Vorliegen eines richtigen Konzepts direkt programmiert, was dann insbesondere bei höherem Komplexitätsgrad der Software zu Designfehlern führen kann. Sowohl für Fehler in der Anforderungsdefinition als auch im Softwaredesign kommen darüber hinaus vielfach Kosten- oder Zeitdruck in Frage. Ein typischer Designfehler ist die Codewiederholung, die zwar nicht unmittelbar zu Programmfehlern führt, aber bei der Softwarewartung, der Modifikation oder der Erweiterung von Programmcode sehr leicht übersehen werden kann und dann unweigerlich zu unerwünschten Effekten führt. Fehler im Bedienkonzept. Das Programm verhält sich anders als es einzelne oder viele Anwender erwarten, obwohl es technisch an sich fehlerfrei arbeitet.
Sonstige Fehlerbegriffe
Laufzeitfehler: Während die vorgenannten Fehler ein tatsächlich fehlerhaftes Programm bedeuten, das entweder nicht ausführbar ist oder fehlerhafte Ergebnisse liefert, kann auch ein „korrektes“ Programm bei seiner Ausführung zu Fehlern führen. Laufzeitfehler sind alle Arten von Fehlern, die auftreten, während das Programm abgearbeitet wird. Je nach Situation kann die Ursache beispielsweise eine unpassenden Programmumgebung sein (z. B. eine falsche Betriebssystem-Version, falsche Parameter beim Aufruf des Programms (auch als Unterprogramm), falsche Eingabedaten etc.) Laufzeitfehler können sich auf die unterschiedlichsten Arten zeigen. Oftmals zeigt das Programm ungewünschtes Verhalten, im Extremfall wird die Ausführung des Programms abgebrochen („Absturz“), oder das Programm geht in einen Zustand über, in dem es keine Benutzereingaben mehr akzeptiert („Einfrieren“, „Hängen“). mini|Auswirkungsbeispiel eines Programmfehlers Wird in Programmiersprachen ohne automatische Speicherbereinigung (etwa C oder C++) Speicher nach der Verwendung nicht mehr freigegeben, so wird durch das Programm auf Dauer immer mehr Speicher belegt. Diese Situation wird Speicherleck genannt. Aber auch in Programmiersprachen mit automatischer Speicherbereinigung (etwa Java oder C#) können ähnliche Probleme auftreten, wenn zum Beispiel Objekte durch systemnahe Programmierung unkontrolliert angesammelt werden. Noch kritischer sind versehentlich vom Programmierer freigegebene Speicherbereiche, die oft trotzdem noch durch hängende Zeiger referenziert werden, da dies zu völlig unkontrolliertem Verhalten der Software führen kann. Manche Laufzeitumgebungen erlauben daher solche programmierbaren Speicherfreigaben grundsätzlich nicht. Des Weiteren gibt es auch Bugs im Zusammenspiel mit anderen Programmen. Fehler im Compiler, der Laufzeitumgebung oder sonstigen Bibliotheken. Solche Fehler sind meist besonders schwer nachzuvollziehen, da das Verhalten des Programms in solchen Fällen nicht seiner Semantik entspricht. Insbesondere von Compiler und Laufzeitumgebung wird daher besondere Zuverlässigkeit erwartet. Ein Regressionsbug (Regression bedeutet „Rückschritt“) ist ein Fehler, der erst in einer späteren Programmversion auftaucht. Dies sind häufig unerkannte Nebeneffekte von Fehlerbehebungen oder Programmänderungen an anderer Stelle.