Ein Programm ist ein Text, der die Berechnung eines Ergebnisses ausdrücken soll, das eine Frage zu den Daten beantwortet. Ein Sortierprogramm nimmt beispielsweise eine Liste von Werten (die Daten) und sollte ein Ergebnis berechnen, bei dem es sich um eine andere Liste derselben Werte handelt, die jedoch nach einer Vergleichsfunktion sortiert ist.
Dieser Text ist formal in einer Sprache auszudrücken, die genau definiert ist (oder sein sollte), sowohl was einen legitimen Programmtext ausmacht als auch wie eine rechnerische Bedeutung diesem Text zugeordnet werden kann. Eine solch genaue Definition ist oft abstrakt (möglicherweise mathematisch) und kann einige konkrete Probleme wie Computereinschränkungen ignorieren.
Dann wird die Sprache implementiert, damit Programme ausgeführt werden können. Es gibt wieder viele Möglichkeiten, eine solche Implementierung durchzuführen, indem ein Integer des ursprünglichen Programmtextes verwendet oder zu einem Zwischencode (z. B. Bytecode) kompiliert wird, um diesen Zwischencode möglicherweise zu interpretieren oder ihn weiter in Maschinencode zu kompilieren. Und es könnte andere Variationen geben. Und natürlich gibt es viele Möglichkeiten, einen Compiler oder einen Interpreter zu schreiben, und viele Maschinen, auf denen sie ausgeführt werden können.
Darüber hinaus kann es mehrere formale Definitionen und mehrere Implementierungen geben, die hoffentlich konsistent sind.
Fehler können in Bezug auf die Struktur einer oder beider formaler Definitionen oder / und einer Implementierung klassifiziert werden. Es kann jedoch zu seltsamen Situationen kommen, in denen Fehler gemäß einer alten Referenzimplementierung klassifiziert werden, die nicht mehr verwendet wird.
Dies bedeutet im Wesentlichen, dass die Klassifizierung von Fehlern ein nicht wirklich stabiles Thema ist . Darüber hinaus können einige Sprachen verschiedene Fehlerebenen unterscheiden, je nachdem, ob etwas definitiv nicht stimmt (das Programm wird nicht einmal ausgeführt) oder ob Sie etwas tun, das nicht empfohlen wird. Dies führt jedoch zu Berechnungen, die möglicherweise sinnvoll sind. Dies spiegelt sich sogar in Funktionen von Programmiersprachen wider, z. B. Ausnahmen, die möglicherweise wiederhergestellt werden oder nicht.
Standardunterscheidungen sind:
Syntaxfehler : Der angegebene Text entspricht nicht der Struktur eines Programmtextes, unabhängig davon, was er bedeuten soll. Dies bezieht sich möglicherweise nur auf eine formale Sprachsyntax, die normalerweise kontextfrei ist. Es kann manchmal weiter gehen und die Überprüfung einiger grundlegender Funktionen wie Variablendeklarationen (falls vorhanden) oder Typkonsistenz umfassen, obwohl diese auch als semantische Fehler betrachtet werden können.
Semantische oder logische Fehler : Dies sind Fehler, die beim tatsächlichen Ausführen des Programms erkannt werden können. Dies liegt daran, dass das Programm auf eine Berechnung stößt, die keinen semantischen Sinn ergibt, z. B. durch Null teilen oder ein Array außerhalb von indizieren Grenzen. Das Aufrufen einer Funktion mit der falschen Anzahl von Argumenten oder mit Argumenten des falschen Typs kann ebenfalls als semantischer Fehler angesehen werden. In einigen Sprachen können Fehler tatsächlich durch Ausnahmen benutzerdefiniert werden, wenn sie einer benutzerdefinierten Semantik auf höherer Ebene für einen Teil seines Programms entsprechen (obwohl es andere Verwendungszwecke von Ausnahmen gibt). Einige dieser Fehler werden manchmal auch als Laufzeitfehler bezeichnet, da sie zur Laufzeit erkannt werden. Sie sollten jedoch nicht mit Hardwarebeschränkungsfehlern verwechselt werden.
Hardwareeinschränkungsfehler : Dies sind Fehler aufgrund der Tatsache, dass sich die Implementierung auf einem realen Computer mit Einschränkungen befindet. Dies kann beispielsweise eine Ganzzahl sein, die zu groß ist, um in ein Speicherwort zu passen, oder ein Mangel an ausreichend Speicher, um eine Datenstruktur zu erstellen. Diese werden normalerweise auch zur Laufzeit erkannt.
In Bezug auf semantische Fehler und Hardwarebeschränkungsfehler ist es manchmal möglich, diese vor der Ausführung des Programms mit einer sogenannten statischen semantischen Analyse zu erkennen. Dies ist häufig bei Deklarationen oder nicht initialisierten Variablen oder bei Typfehlern oder bei der Division durch Null und einigen Array-gebundenen Überprüfungen der Fall, kann jedoch viel weiter gehen. Die statische semantische Analyse ist auch in Compilern für viele Optimierungstechniken wichtig. Es gibt oft eine Trennung zwischen statischer und dynamischer Semantik. Die beste Definition, die ich mir vorstellen kann, ist, dass die statische Semantik Eigenschaften betrifft, die zum Zeitpunkt der Kompilierung ohne die tatsächlichen Daten entscheidbar sind. Die Division durch Null wäre also im Allgemeinen nicht Teil der statischen Semantik. Dies bedeutet, dass beim Kompilieren manchmal noch einige dynamische semantische Fehler erkannt werden können. Gleiches gilt für Hardwarebeschränkungsfehler.
Aber jede Sprache Designer oder Implementierer hat ein Recht , Fehler zu klassifizieren , wie er will , es sei denn , durch einen Vertrag oder eine Lizenz gebunden. Dies kann bei Ihrem PHP-Beispiel durchaus der Fall sein. Und jeder kann genauso gut zwischen semantischen und logischen Fehlern unterscheiden, obwohl ich nicht wissen würde, wie man einen Unterschied definiert, es sei denn, man wird möglicherweise ausführlich über diese Fehler informiert. Man könnte verwendet werden, um einen Fehler in der Absicht (logischer Fehler) zu bezeichnen, und wäre vom System nicht erkennbar.
Beachten Sie, dass ein Programm möglicherweise andere Arten von Fehlern enthält , die vom System normalerweise nicht erkannt werden. Dies schließt insbesondere Inkonsistenzen des Programms mit seiner Spezifikation (oder dem, was ich als Fehler in der Absicht bezeichnet habe: Der Benutzer tut nicht das, was er meinte, tun) oder möglicherweise Fehler in der Spezifikation selbst ein. Es können auch Fehler aufgrund von Hardwareeinschränkungen auftreten, z. B. Rundungsfehler beim Arbeiten mit reellen Zahlen.