Ich habe über PHP gelesen und viele Autoren erwähnen semantische und logische Fehler getrennt. Als Beispiel für einen semantischen Fehler geben sie eine Funktion an, die mit einer falschen Anzahl von Parametern aufgerufen wird: Diese wird vom Parser nicht abgefangen, gibt aber beim Ausführen einen Fehler aus.
In Sprachen wie C ++ wird dies jedoch vom Compiler abgefangen. Ich würde sagen, dass es dann ein Syntaxfehler ist. Was ist dann der Unterschied zwischen einem semantischen und einem logischen Fehler?
Zum Beispiel verwendet der Autor in Wie man wie ein Informatiker denkt "Logikfehler" und "semantischer Fehler" synonym. Auf der anderen Seite in Visual Basic .NET. Primer Plus , "Logikfehler" wird von "semantischer Fehler" getrennt.
Antworten:
Ich denke , die meisten wahrscheinlich die Erklärung für einige Autoren „Logikfehler“ und „semantische Fehler“ austauschbar und einige Autoren mit einer Unterscheidung Zeichnung einfach ist , dass sie nicht haben eine genaue allgemein akzeptierte Definition und damit die Menschen , die Terminologie etwas anders verwenden. Ich würde nicht daran hängen bleiben.
Sowohl "Logik" als auch "Semantik" implizieren etwas mit der Bedeutung der Programmierung, so dass es leicht wäre, sie als gleich anzusehen.
Wenn ich eine Unterscheidung treffen würde, ist eine nützliche, die ich sehen kann, dass ein logischer Fehler ist, wenn das Programm etwas anderes bedeutet als das, was der Programmierer beabsichtigt hat, und ein semantischer Fehler ist, wenn das Programm am Ende nichts bedeutet (konsistent) überhaupt. Mit diesen Definitionen können Sie logische Fehler entweder als Obermenge semantischer Fehler betrachten oder logische Fehler schließen Fehler aus, die dazu führen, dass das Programm inkonsistent ist.
Der folgende Pseudocode enthält beispielsweise nur einen logischen Fehler:
Die Bedeutung dieses Programms (nur so wie es ist und ohne Berücksichtigung der Absicht des Programmierers) ist vollkommen einfach und konsistent. Aber es bedeutet nicht, was der Programmierer damit gemeint hat.
OTOH, der folgende Pseudocode enthält einen semantischen Fehler:
Zumindest, wenn wir davon ausgehen, dass das Hinzufügen einer Zeichenfolge und einer Zahl nichts bedeutet. In Sprachen wie PHP es tut etwas bedeuten, und dies würde nicht ein semantischer Fehler.
Ihr Beispiel eines semantischen Fehlers in PHP als Aufruf einer Funktion mit einer falschen Anzahl von Parametern ist tatsächlich interessant, da es fraglich ist, ob Sie dies als semantischen Fehler bezeichnen sollten (mit der von mir verwendeten Definition).
Funktionen werden zur Laufzeit in PHP dynamisch definiert. So eine Funktion mit einer falschen Anzahl von Parametern aufrufen könnte als logische Fehler angesehen werden; Möglicherweise wurde die falsche include-Anweisung ausgeführt, wodurch eine andere Funktion mit demselben Namen eingefügt wurde als die, zu der der Aufruf gehen sollte. Selbst wenn nicht, bedeutet das Aufrufen einer Funktion mit der falschen Anzahl von Argumenten etwas ; es bedeutet, die Funktion mit diesem Namen nachzuschlagen und diese Argumente zu übergeben. Es stellt sich heraus, dass der Interpreter diese Anforderungen nur zur Laufzeit ausführen kann. genauso
x / y
bedeutet etwas, kann aber unmöglich ausgeführt werden, wenny
es zur Laufzeit 0 ist.Letztendlich hängt es sehr stark von der Sprache ab, über die Sie sprechen, und davon , wie Sie Fehler anhand einer Unterscheidung wie der hier vorgenommenen zwischen logischen und semantischen Fehlern klassifizieren (auch wenn es nicht genau die ist, die ich mache) Weisen Sie Programmen in der Sprache eine Bedeutung zu . Die am häufigsten verwendeten Sprachen haben keine Standardmethode, um ihren Programmen eine Bedeutung zuzuweisen, was bedeutet, dass jeder eine etwas andere Methode verwendet (obwohl sich die Interpretation aller in fast allen betrieblichen Auswirkungen sehr genau einig wäre ) und die "Logik" analysiert "vs" semantische "Unterscheidung unterschiedlich.
Eine andere ähnliche Sichtweise wäre zu sagen, dass semantische Fehler alles sind, was die Programmiersprache veranlasst, das Programm als ungültig abzulehnen (abgesehen von syntaktischen Fehlern, obwohl Sie diese wiederum als Teilmenge semantischer Fehler bezeichnen könnten, wenn Sie möchten). Wenn die Programmiersprache das Programm akzeptiert, bedeutet dies etwas , und wenn es zur Laufzeit fehlschlägt, ist dies das Ergebnis eines Logikfehlers. Hiermit wird die Implementierung der Programmiersprache (Interpreter, Compiler + Laufzeitsystem, was auch immer) als Definition der Bedeutung von Programmen zugewiesen.
quelle
Es ist möglich, viele Kategorien von Fehlern in Programmen anhand des Punktes zu unterscheiden, an dem sie sich manifestieren. Einige Kategorien treten in bestimmten Kontexten nicht auf (abhängig von der Programmiersprache, dem Design des Programms, der Verwendung des Programms…). Die Terminologie variiert stark zwischen den Gemeinden. Ich werde eine Typologie der Hauptkategorien zeigen; Denk daran, dass
Sie können verschiedene Kategorien von Fehlern anhand des Punktes unterscheiden, an dem sie bemerkt werden.
Syntaxfehler
Der Compiler oder Interpreter sagt Ihnen, dass das, was Sie geschrieben haben, nicht einmal Sinn macht. In den meisten Sprachen ist dies ein schwerwiegender Fehler, durch den das Programm nicht einmal ausgeführt werden kann.
Beispiel: eine fehlende enge Klammer.
Statische Typfehler und andere Compilerfehler
Der Compiler oder Interpreter teilt Ihnen mit, dass dies zwar Sinn macht, was Sie angefordert haben, dies jedoch keinen Sinn ergibt. Die Unterscheidung zwischen Syntaxfehlern und anderen Arten von Compilerfehlern hängt vom internen Compilerdesign oder manchmal vom Design der Programmiersprache ab.
Beispiel: Verwenden einer nicht definierten Variablen (dies wird häufig als Syntaxfehler angesehen, aber nicht immer)
In statisch typisierten Sprachen lehnt der Compiler Programme ab, die einige Arten ungültiger Operationen versuchen. In dynamisch typisierten Sprachen sind solche Fehler Laufzeitfehler, entweder schwerwiegend oder nicht. Beispiel: Versuch, eine Ganzzahl durch eine Zeichenfolge zu teilen.
Startfehler
Dies ist die erste Fehlerkategorie, die der Person, die das Programm ausführt, und nicht der Person, die das Programm erstellt, angezeigt wird.
Das Programm startet nicht oder erreicht keinen Zustand, in dem es tatsächlich etwas tut.
Beispiel: Versuch, eine externe Bibliothek zu verwenden, die auf dem System nicht vorhanden ist.
Beispiel: Jeder Syntax- oder Kompilierungsfehler in einer interpretierten Sprache (wobei der Programmierer den Quellcode verteilt).
Schwerwiegende Laufzeitfehler
Irgendwann funktioniert das Programm nicht mehr.
Beispiel: Speicherzugriffsverletzung (Versuch, auf Speicher zuzugreifen, der dem Programm nicht zugeordnet ist)
Beachten Sie, dass ausreichend komplexe Programme möglicherweise versuchen, nahezu jeden Fehler abzufangen und ihn in behebbare Fehler umzuwandeln.
Unerwartete, aber behebbare Laufzeitfehler
Einige Komponenten des Programms funktionieren nicht mehr, aber das Programm läuft weiter. Beispiel: Nicht genügend Arbeitsspeicher (wenn das Programm dafür ausgelegt ist, dies ordnungsgemäß zu handhaben)
Beispiel: Ein Prozess in einer Multiprozessanwendung stürzt ab, die anderen Prozesse werden jedoch weiterhin ausgeführt
Erwartete Laufzeitfehler
Es wird eine Fehlerbedingung erwartet, für die jedoch programmiert wurde. Dies ist nur ein normales Verhalten, das auf ein externes Ereignis reagiert, das irgendwie „schlecht“ ist, aber passieren kann. Wenn Sie das Programm als Ganzes betrachten, sind dies keine wirklichen Fehler.
Beispiel: Datei nicht gefunden
Beispiel: Netzwerkunterbrechung
Beispiel: Ungültige Benutzereingabe
Programmierfehler
Das Programm macht etwas, aber das ist nicht das, was es gemäß seiner Spezifikation tun soll. Es gibt einen Unterschied zwischen dem, was der Programmierer vorhatte und dem, was der Quellcode tatsächlich bedeutet.
Beispiel: Eine Webanwendung soll das Hochladen einer Datei ermöglichen, funktioniert jedoch nicht bei Dateinamen, die Leerzeichen enthalten. Die Anwendung lehnt die Datei ab und arbeitet weiter.
Beispiel: Ein Programm zum Multiplizieren einer Zahl gibt ein Ergebnis zurück, aber die mathematische Operation wird nicht korrekt ausgeführt.
Spezifikationsfehler
Das Programm unternimmt etwas und entspricht seiner Spezifikation oder Dokumentation. Nach Überlegungen ist das Verhalten des Programms in dieser Situation jedoch nicht gut. („Nicht gut“ ist natürlich eine subjektive Beurteilung.)
Beispiel: Komponente 1 erwartet eine durch Leerzeichen getrennte Liste von Dateinamen. Komponente 2 sendet ihm einen einzelnen Dateinamen, der Leerzeichen enthält. Die beiden Komponenten wurden nicht sorgfältig für die Zusammenarbeit entwickelt.
Beispiel: Ein Programm zur Vorhersage des Wetters kündigt Regen an, der nicht kommt, weil die Modellierung der physischen Welt nicht gut genug war.
Es ist ziemlich typisch, 2–4 als semantische Fehler und 7–8 als logische Fehler zu betrachten. (Beachten Sie jedoch erneut, dass die Terminologie variieren kann.) Wiederherstellbare Laufzeitfehler sind keine Fehler des gesamten Programms, sondern können als Laufzeitfehler eines Teils davon angesehen werden.
Es gibt eine andere Terminologie, die dies berücksichtigt
Dies kann eine ziemlich genaue Unterscheidung sein, wenn Sie eine bestimmte Sprache und eine bestimmte Typprüfung berücksichtigen. Wenn Leute diese Begriffe verwenden, haben sie jedoch oft eine sehr ungenaue Vorstellung davon, was dieser hypothetische Compiler sein würde. Wenn Sie beispielsweise in Java programmieren, wird die Übergabe der falschen Anzahl von Argumenten vom Compiler abgefangen. Wenn Sie in PHP programmieren, wird es vom Laufzeitsystem abgefangen. Wenn Sie in Perl programmieren, wird es wahrscheinlich nicht abgefangen (wenn keine Argumentdeklaration vorliegt, werden zusätzliche Argumente ignoriert und fehlende Argumente erzeugen einen Standardwert).
Oder, um ein anderes Beispiel zu nennen: Angenommen, Sie haben ein Array mit 10 Elementen und versuchen, auf das 11. zuzugreifen. In einigen Sprachen wie C führt dies dazu, dass Ihr Programm auf eine nicht verwandte Speicherzone zugreift, was zu unvorhersehbarem Verhalten führt. In anderen Sprachen wird dadurch eine Ausnahme ausgelöst. Abhängig davon, ob der Programmierer dies erwartet hat, kann dies ein semantischer Fehler sein (der Programmierer hat erwartet, dass der Index außerhalb der Grenzen liegt, dies jedoch nicht überprüft hat), ein logischer Fehler (der Programmierer hat fälschlicherweise angenommen, dass der Index immer gültig ist ) oder überhaupt kein Fehler (der Programmierer stützte sich auf die Ausnahme, um zu testen, ob der Array-Index innerhalb der Grenzen des Arrays lag).
Die Moral der Geschichte ist, dass diese Klassifikationen sehr unterschiedlich sind. Legen Sie nicht viel Wert darauf, welche Fehler von welchen Autoren in welche Kategorien eingeordnet werden. Das Wichtigste ist, die Beziehung zwischen dem, was Sie schreiben, und dem, was das Programm tun sollte, zu verstehen. Als Programmierer besteht Ihre Aufgabe darin, die große Lücke zwischen dem, was ich schreibe, und dem, was ich meine, zu schließen . Wenn etwas in die Lücke fällt, hängen Sie nicht daran, es mit einem Etikett zu versehen. Konzentrieren Sie sich darauf, zu verstehen, was falsch läuft und wie Sie es beheben können.
quelle
Grundsätzlich muss man sich zuerst die Sprachen selbst ansehen.
PHP ist eine Interpretersprache, dh die Skripte werden jedes Mal zur Laufzeit kompiliert und ausgeführt. C ++ ist eine Compilersprache, dh die Skripte werden einmal zur Erstellungszeit mit einem Compiler kompiliert und können dann ausgeführt werden.
Daher erkennen beide Compiler den semantischen Fehler aus Ihrem Beispiel, aber der PHP-Compiler tut dies zur Laufzeit und der C ++ - Compiler zur Kompilierungszeit.
Eine gute Erklärung für Ihre Frage finden Sie bei Wikipedia und hier (Unterschied zwischen Semantik und Syntax)
quelle
Meine Vermutung:
quelle
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.
quelle
Gemäß meinen Kursnotizen für höhere Computer sind semantische Fehler und logische Fehler nur unterschiedliche Namen für dieselbe Sache.
quelle