|
Article on other languages:
|
Ein Programmfehler oder Softwarefehler, häufig auch im Deutschen mit dem englischen Wort Bug (genau genommen Wanze, im erweiterten Sinne auch für jedes andere Insekt; Aussprache [bʌg]) bezeichnet, ist ein Ausdruck aus dem EDV-Bereich. Ein Fehler tritt in Computerprogrammen auf, wenn der Programmierer einen bestimmten Zustand in der Programmlogik nicht berücksichtigt hat, oder wenn die Laufzeitumgebung an sich fehlerhaft arbeitet. Auch Unvollständigkeit, Ungenauigkeiten, Mehrdeutigkeiten o. ä. in der Spezifikation des Programms können zu Fehlern führen, bzw. als solche interpretiert werden. Es gibt eine Regel, nach der ein Computerprogramm ab einer bestimmten Größe immer auch Programmfehler beinhaltet. Programmierfehler lassen sich auch bei sorgfältigster Programmierung nicht vermeiden. Man schätzt, dass pro 1000 Zeilen Code im Mittel etwa zwei Fehler auftreten. Die Anzahl von Fehlern zur Lebenszeit eines komplexen Systems verhält sich nach der sogenannten Badewannenkurve. Diese besagt, dass für neue Produkte auch die Zahl der Fehler hoch ist. Die Fehler werden zum Großteil behoben, wonach eine Phase mit wenig Fehlern erreicht wird. Gegen Ende der Nutzungszeit steigt die Zahl der Fehler wieder an, was erheblich zur Softwarealterung beiträgt. Um Fehler in Programmen besser verstehen zu können, gibt es Programme, sogenannte Debugger, mit denen man ein Programm, welches man analysiert, schrittweise ablaufen und sich dabei sämtliche internen Zustände (Variablen) des Programms anzeigen lassen kann. So genannte Bug-Tracker (wie Bugzilla oder Mantis) dienen der Erfassung und Dokumentation von Fehlerberichten. Daneben nehmen sie auch Verbesserungsvorschläge und Wünsche der Nutzer oder allgemeine Vorgänge auf.
Das engl. Wort „Bug“ als Synonym für ProgrammfehlerDas Wort „Bug“ wurde schon im 19. Jahrhundert für kleine Fehler in mechanischen und elektrischen Teilen verwendet. Knistern und Rauschen in der Telefonleitung würde z. B. daher rühren, dass kleine Tiere („Bugs“ (engl: Wanze)) an der Leitung knabbern. Thomas Edison hat 1878 an seinen Freund Tivadar Puskás (dem Erfinder der Telefonzentrale und des Telefongraphen) einen Brief über die Entwicklung seiner Erfindungen geschrieben, in dem er kleine Störungen und Schwierigkeiten als „Bugs“ bezeichnete („… that ‚Bugs‘ – as such little faults and difficulties are called – show themselves…“). Die Erfindung des Begriffs in Bezug auf Computer geht möglicherweise auf die Computerpionierin Grace Hopper zurück.[1] 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 und in das Logbuch mit den Worten „First actual case of bug being found.“ („Das erste Mal, dass tatsächlich ein Bug gefunden wurde.“) geklebt. Die Legende von der Begriffsfindung hält sich hartnäckig, obwohl die Logbuch-Eintragung gerade auf die frühere Verwendung des Begriffs hinweist. 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. Zur Zeit befindet sich diese Logbuch-Seite mit der Motte am Smithsonian Institute. Arten von ProgrammfehlernIn der Softwaretechnik wird zwischen folgenden Typen von Fehlern in Programmen unterschieden:
Bei manchen Projekten spricht man dann zum Beispiel von Metabugs, wo ein Bug ein Element einer Aufgabenliste darstellt. Bei einigen Projekten spricht man stattdessen von „Issues“ (Angelegenheiten), da sich dieser Ausdruck nicht auf Programmfehler beschränkt. Vermeidung und Behebung von ProgrammfehlernGenerell gilt der Leitsatz: Je früher in einem Entwicklungsprozess der Fehler auftritt und je später er entdeckt wird, umso aufwendiger wird es, den Fehler zu beheben. Während der PlanungAm wichtigsten ist eine gute und geeignete Planung des Entwicklungsprozesses. Hierfür gibt es bereits etliche Prozessmodelle, aus denen ein geeignetes ausgewählt werden kann. In der AnalysephaseEin Problem ist, dass die Korrektheit eines Programms nur gegen eine entsprechend formalisierte Spezifikation bewiesen werden kann. Eine solche Spezifikation zu erstellen kann jedoch im Einzelfall ähnlich kompliziert und fehlerträchtig sein, wie die Programmierung des Programms selbst. Auch die Entwicklung immer abstrakterer Programmierparadigmen und Programmierstile wie die objektorientierte Programmierung, Design By Contract und die aspektorientierte Programmierung dienen unter anderem der Fehlervermeidung und Vereinfachung der Fehlersuche. Aus den zur Verfügung stehenden Techniken für das Problem ist eine geeignete auszuwählen. Ein wichtiger Punkt hierbei ist aber auch, dass für das jeweilige Paradigma erfahrene Programmierer zur Verfügung stehen müssen, sonst entsteht oft der gegenteilige Effekt. Ferner ist es sehr nützlich, von den Entwicklungswerkzeugen möglichst viele Aufgaben der Fehlervermeidung zuverlässig und automatisch erledigen zu lassen. Dies betrifft zum einen bereits Kontrollen wie Sichtbarkeitsregeln und Typsicherheit, sowie die Vermeidung von Zirkelbezügen, die bereits vor der Übersetzung von Programmen vom Compiler übernommen werden können, aber auch Kontrollen, die erst zur Laufzeit durchgeführt werden können, wie zum Beispiel Indexprüfung bei Datenfeldern oder Typprüfung bei Objekten der objektorientierten Programmierung. In der DesignphaseSoftwareexperten sind sich darüber einig, dass praktisch jedes nicht-triviale Programm Fehler enthält. Deshalb wurden Techniken entwickelt, mit Fehlern innerhalb von Programmen tolerant umzugehen. Zu diesen Techniken gehören defensives Programmieren, Ausnahmebehandlung, Redundanz und die Überwachung von Programmen (z. B. durch Watchdog-timer) sowie die Plausibilisierung des Programmes während der Entwicklung und der Daten während des Programmablaufs. Bei der ProgrammierungDarüber hinaus wird eine Reihe fortgeschrittener Anwendungen angeboten, die entweder den Quellcode oder den Binärcode analysieren und versuchen, häufig gemachte Fehler automatisiert zu finden. In diese Kategorie fallen etwa Programme zur Ausführungsüberwachung, die üblicherweise fehlerhafte Speicherzugriffe und Speicherlecks zuverlässig aufspüren. Beispiele sind das frei erhältliche Tool Valgrind und das kommerzielle Purify. Eine weitere Kategorie von Prüfprogrammen umfasst Anwendungen, die Quell- oder Binärcode statisch analysieren und etwa nicht geschlossene Ressourcen und andere Probleme auffinden und melden können. Darunter fallen etwa Findbugs, Lint und Splint. Beim TestenEs ist durchaus sinnvoll, dass der Test vor dem eigentlichen Programm entwickelt wird. Damit wird erreicht, dass nicht ein Test geschrieben wird, der zu dem bereits geschriebenen Programm passt. Dies kann durch Ermittlung von Testfällen anhand der Spezifikation bereits während der Analyse- bzw. Designphase erfolgen. Die Ermittlung von Testfällen in diesem frühen Stadium der Softwareentwicklung ermöglicht zudem die Prüfung der Anforderungen an das Programm auf Testbarkeit und Vollständigkeit. Die anhand der Spezifikation ermittelten Testfälle stellen die Basis für die Abnahmetests und können kontinuierlich über den gesamten Entwicklungsprozess verfeinert werden. Manche Softwareanbieter führen Testphasen teilweise öffentlich durch und geben Betaversionen heraus, um die unvorhersehbar vielfältigen Nutzungsbedingungen verschiedener Anwender durch diese selbst testen und kommentieren zu lassen. Man nennt dies auch scherzhaft „Bananensoftware“, weil sie „erst beim Kunden reift“. Diese Bezeichnung wird ebenfalls oft abwertend gebraucht, um die geringe Wertschätzung zu früher Vermarktung ungenügend entwickelter bzw. schlecht getesteter Software zum Ausdruck zu bringen. Im BetriebTritt ein Fehler während des Betriebs auf, so muss versucht werde, seine Auswirkungen möglichst gering zu halten und seinen Wirkungskreis durch Schaffung von "Schutzwällen" oder "Sicherungen" einzudämmen. Dies erfordert zum einen Möglichkeiten der Fehlererkennung und zum anderen, adäquat auf einen Fehler reagieren zu können. Ein Beispiel zur Fehlererkennung zur Laufzeit eines Computerprogrammes sind Assertions, mit deren Hilfe Bedingungen abgefragt werden, die gemäß Programmdesign immer erfüllt sind. Weitere Mechanismen sind Ausnahmebehandlungen wie Trap und Exception. FehlerfreiheitIn Spezialfällen ist ein Beweis der Fehlerfreiheit eines Programms möglich. Insbesondere in Bereichen, in denen der Einsatz von Software mit hohen finanziellen, wirtschaftlichen oder menschlichen Risiken verbunden ist, wie z. B. bei militärisch oder medizinisch genutzter Software oder in der Luft- und Raumfahrt, verwendet man zudem eine (formale) Verifizierung genannte Methode, bei der die Korrektheit einer Software formal-mathematisch nachgewiesen wird. Dieser Methode sind allerdings wegen des enormen Aufwands enge Grenzen gesetzt und sie ist daher bei komplexen Programmen praktisch unmöglich durchzuführen (siehe auch Berechenbarkeit). Allerdings gibt es mittlerweile Werkzeuge, die diesen Nachweis laut eigenen Angaben zumindest für Teilbereiche (Laufzeitfehler) schnell und zuverlässig erbringen können. Neben der mathematischen Verifizierung gibt es noch eine praxistaugliche Form der Verifizierung, die durch die Qualitätsmanagement-Norm ISO 9000 beschrieben wird. Bei ihr wird nur dann ein Fehler konstatiert, wenn eine Anforderung nicht erfüllt ist. Umgekehrt kann demnach ein Arbeitsergebnis (und damit auch Software) als fehlerfrei bezeichnet werden, wenn es nachweisbar alle Anforderungen erfüllt. Die Erfüllung einer Anforderung wird dabei durch Tests festgestellt. Wenn alle Tests das erwartete Ergebnis bringen, ist eine Anforderung erfüllt. Folgen von ProgrammfehlernDie Folgen eines Programmfehlers können außerordentlich sein und sich in vielfältiger Weise zeigen:
Reproduzierbarkeit von ProgrammfehlernManche Programmfehler sind nur äußerst schwer oder gar nicht zuverlässig reproduzierbar. Bei der Wiederholung eines zuvor gescheiterten Vorgangs unter scheinbar unveränderten Bedingungen ist die Wahrscheinlichkeit hoch, dass sich diese Fehler nicht erneut äußern. Es gibt zwei mögliche Gründe für dieses Verhalten: Zum einen kann es zu Verzögerungen zwischen der Fehleraktivierung und dem letztlich auftretenden Problem beispielsweise einem Programmabsturz kommen, welche die tatsächliche Ursache verschleiern und deren Identifikation erschweren. Zum anderen können andere Elemente des Softwaresystems (Hardware, Betriebssystem, andere Programme) das Verhalten der Fehler in dem betrachteten Programm beeinflussen. Ein Beispiel hierfür sind Fehler, die in nebenläufigen Umgebungen mit mangelnder Synchronisation (genauer: Sequentialisierung) auftreten. Wegen der hieraus folgenden Wettlaufsituationen (Race Conditions) können die Prozesse in einer Reihenfolge abgearbeitet werden, welche zu einem Laufzeitfehler führt. Bei einer Wiederholung der gleichen Aktion ist es möglich, dass die Reihenfolge der Prozesse unterschiedlich ist und kein Problem auftritt. MandelbugEin Programmfehler, dessen Ursachen – in mindestens einer der beschriebenen Formen – so komplex sind, dass sein Verhalten chaotisch oder gar nichtdeterministisch erscheint, wird in Anspielung auf den Mathematiker Benoît Mandelbrot als „Mandelbug“ bezeichnet.[9] HeisenbugEine Untergruppe von Mandelbugs sind Programmfehler, die ihr Verhalten verändern, wenn man versucht, sie (zum Beispiel mithilfe eines Debuggers) im Programmcode aufzuspüren. Eine mögliche Ursache für eine solche Verhaltensänderung ist, dass der Einsatz eines Analysewerkzeuges die Rahmenbedingungen (insbesondere das zeitliche Verhalten des Softwaresystems) beeinflussen und somit das Auftreten eines Fehlers verhindern kann. Im Programmiererjargon spricht man dabei manchmal scherzhaft von „Heisenbug“, in Anlehnung an Werner Heisenbergs Unschärferelation.[10] BohrbugDas komplementäre Antonym zu Mandelbug ist „Bohrbug“, was für einen Fehler steht, der sich unter bestimmten, einfach zu fassenden Bedingungen zuverlässig äußert und deshalb – analog zu Niels Bohrs Atommodell – vergleichsweise einfach zu verstehen ist.[11] [12] SchroedinbugEin Programmfehler, der sich bis zu seinem Auffinden im Quellcode noch nie bemerkbar gemacht hat, wird als Schroedinbug bezeichnet (in Anlehnung an Schrödingers Katze des österreichischen Physikers Schrödinger).[13] Siehe auchLiteratur
Einzelnachweise
Weblinks
|
This article is from Wikipedia. All text is available under the terms of the GNU Free Documentation License.
Mercedes Car
This site monitored by SitePinger.net