Undefiniertes Verhalten ist einer der Aspekte der Sprachen C und C++, die für Programmierer, die aus anderen Sprachen kommen, überraschend sein können (andere Sprachen versuchen, dies besser zu verbergen). Grundsätzlich ist es möglich, C++-Programme zu schreiben, die sich nicht vorhersehbar verhalten, auch wenn viele C++-Compiler keine Fehler im Programm melden!
Schauen wir uns ein klassisches Beispiel an:
#include <iostream>
int main()
{
char* p = "hello!\n"; // yes I know, deprecated conversion
p[0] = 'y';
p[5] = 'w';
std::cout << p;
}
Die Variable p
zeigt auf das String-Literal "hello!\n"
und die beiden folgenden Zuweisungen versuchen, dieses Zeichenfolgenliteral zu ändern. Was macht dieses Programm? Gemäß Abschnitt 2.14.5 Absatz 11 des C++-Standards ruft es auf undefiniertes Verhalten :
Die Auswirkung des Versuchs, ein String-Literal zu ändern, ist undefiniert.
Ich höre schon die Leute schreien: "Aber warte mal, ich kann das doch problemlos kompilieren und bekomme die Ausgabe yellow
" oder "Was meinen Sie mit undefiniert, String-Literale werden im Nur-Lese-Speicher gespeichert, so dass der erste Zuweisungsversuch zu einem Core-Dump führt". Genau das ist das Problem mit dem undefinierten Verhalten. Im Grunde erlaubt der Standard alles, was passieren kann, sobald man undefiniertes Verhalten aufruft (sogar nasale Dämonen). Wenn es ein "richtiges" Verhalten gemäß Ihrem mentalen Modell der Sprache gibt, ist dieses Modell einfach falsch; der C++-Standard hat die einzige Stimme, Punkt.
Andere Beispiele für undefiniertes Verhalten sind der Zugriff auf ein Array außerhalb seiner Grenzen, Dereferenzierung des Null-Zeigers , Zugriff auf Objekte nach Ende ihrer Lebensdauer oder Schreiben vermeintlich kluge Ausdrücke wie i++ + ++i
.
In Abschnitt 1.9 des C++-Standards werden auch die beiden weniger gefährlichen Brüder des undefinierten Verhaltens erwähnt, nicht spezifiziertes Verhalten y implementierungsdefiniertes Verhalten :
Die semantischen Beschreibungen in dieser Internationalen Norm definieren eine parametrisierte, nicht-deterministische abstrakte Maschine.
Bestimmte Aspekte und Funktionen der abstrakten Maschine werden in dieser Internationalen Norm wie folgt beschrieben Implementierung definiert (zum Beispiel, sizeof(int)
). Diese bilden die Parameter der abstrakten Maschine. Jede Implementierung muss eine Dokumentation enthalten, die ihre Eigenschaften und ihr Verhalten in dieser Hinsicht beschreibt.
Bestimmte andere Aspekte und Operationen der abstrakten Maschine werden in dieser Internationalen Norm beschrieben als nicht spezifiziert (z. B. die Reihenfolge der Auswertung der Argumente einer Funktion). Soweit möglich, definiert diese Internationale Norm eine Reihe von zulässigen Verhaltensweisen. Diese definieren die nicht-deterministischen Aspekte der abstrakten Maschine.
Bestimmte andere Tätigkeiten werden in diesem Internationalen Standard beschrieben als undefiniert (z. B. die Auswirkung der Dereferenzierung des Null-Zeigers). [ Hinweis : Diese Internationale Norm stellt keine Anforderungen an das Verhalten von Programmen, die undefiniertes Verhalten enthalten. - Endnote ]
Konkret heißt es in Abschnitt 1.3.24:
Zulässiges undefiniertes Verhalten reicht von völliges Ignorieren der Situation mit unvorhersehbaren Ergebnissen zu einem für die Umgebung charakteristischen, dokumentierten Verhalten während der Übersetzung oder Programmausführung (mit oder ohne Ausgabe einer Diagnosemeldung), zum Abbruch einer Übersetzung oder Ausführung (mit Ausgabe einer Diagnosemeldung).
Was können Sie tun, um nicht auf undefiniertes Verhalten zu stoßen? Grundsätzlich müssen Sie Folgendes lesen gute C++ Bücher von Autoren, die wissen, wovon sie sprechen. Vermeiden Sie Internet-Tutorials. Vermeiden Sie Bullschildt.
1 Stimmen
Ich war mir ziemlich sicher, dass wir das schon einmal gemacht haben, aber ich kann es nicht finden. Siehe auch: stackoverflow.com/questions/2301372/
2 Stimmen
Aus den comp.lang.c FAQ: Es wird zwischen implementierungsdefiniertem, nicht spezifiziertem und undefiniertem Verhalten unterschieden. Was bedeuten diese Begriffe?
1 Stimmen
theunixshell.blogspot.com/2013/07/
1 Stimmen
Hier ist eine interessante Diskussion (der Abschnitt "Anhang L und unbestimmtes Verhalten").