Undefiniertes VerhaltenUndefiniertes Verhalten beschreibt in der Informatik Code, dessen Verhalten nicht spezifiziert ist und deshalb von verschiedenen Implementierungen von Compilern unterschiedlich behandelt werden kann. Dies ist eine Eigenschaft einiger Programmiersprachen, wie beispielsweise C[1] oder C++. Die Semantik bestimmter Operationen ist in den Standards dieser Sprachen nicht definiert, wodurch eine Implementierung davon ausgehen kann, dass diese Operationen im Normalfall nicht vorkommen. Dadurch stimmt das Verhalten der Implementierung in jedem Fall mit den Standards der Sprache überein. Es ist die Aufgabe des Programmierers, nie Code zu schreiben, der undefiniertes Verhalten auslöst. BeispieleIn C führt beispielsweise die Division durch Null zu undefiniertem Verhalten: int f(int x) {
return x/0; // undefiniert
}
Ebenso die Dereferenzierung (Verfolgung) eines Nullzeigers: int* p = NULL;
int i = *p; // undefiniert
OptimierungsmöglichkeitenWenn eine Operation vom Standard mit bestimmten Werten als undefiniert erklärt wird, darf der Compiler davon ausgehen, dass die ungültigen Werte niemals vorkommen. Dabei darf der Compiler diese Annahme auf folgende Operationen anwenden. Ein Beispiel wäre die Dereferenzierung eines Zeigers. Falls der Zeiger int get_int(int* p) {
int i = *p; // Dereferenzierung -> p != NULL
if(p == NULL) {
return 42;
}
return i;
}
Der komplette int get_int(int* p) {
// p darf hier alles sein
if(p == NULL) {
return 42;
}
int i = *p; // Dereferenzierung -> p != NULL
return i;
}
Außerdem darf Folgendes auch komplett entfernt werden: if(p == NULL) {
int i = *p;
printf("Hello");
}
UnterkategorienEs wird zwischen undefinierten Operationen und undefinierten Werten unterschieden. Während das Lesen durch einen Nullzeiger eine undefinierte Operation ist (möglicherweise zum Programmabsturz führt), resultiert das Lesen von nicht initialisiertem Speicher nur in einem undefinierten Wert. Wenn beispielsweise ein unbekannter Wert mit exklusiv-oder mit sich selbst verknüpft wird, ist er immer 0, somit ist Folgendes komplett legal: int value; // Startwert von value nicht gesetzt
value ^= value; // exklusiv-oder Verknüpfung
// value ist nun definiert als 0
Dieses ähnelt dem Herunterzählen bis auf 0 (bei unsigned value;
while(value != 0) { --value; }
Auf diese Weise wird in der Sprache Brainfuck eine Speicherzelle auf 0 gesetzt, der Code dafür ist Einzelnachweise
|