Kürzestes undefiniertes Verhaltensbeispiel in C ++ [geschlossen]


8

Was ist der kürzeste, wohlgeformte C ++ - Code, der undefiniertes Verhalten aufweist?


1
Was meinst du mit "lauffähig"? Wenn es UB hat, gibt es keine Garantie, dass es ausgeführt werden kann.
R. Martinho Fernandes

@ R.MartinhoFernandes gut, ich meine, dass es beginnt.
Luchian Grigore

@LuchianGrigore, der sehr vom Compiler (Version) abhängig ist.
Rubenvb

1
Definieren Sie "Exponate". Muss es etwas zeigen? Oder reicht es aus, dass der interne Speicherstatus irgendwann während des Programms undefiniert ist?
Herr Lister

Antworten:


12
int main(){main;}

3.6.1 Hauptfunktion [basic.start.main]

3 - [...] Die Funktion main darf nicht innerhalb eines Programms verwendet werden.

Bearbeiten: Dies ist diagnostizierbar, also nicht UB.


int main(){for(;;);}

1.10 Multithread-Ausführungen und Datenrennen [intro.multithread]

24 - Die Implementierung kann davon ausgehen, dass ein Thread möglicherweise eine der folgenden Aktionen ausführt: - Beenden, - Aufrufen einer Bibliotheks-E / A-Funktion, - Zugreifen auf oder Ändern eines flüchtigen Objekts oder - Ausführen einer Synchronisationsoperation oder einer atomaren Operation .


int main(){int i=i;}

4.1 L-Wert-zu-Wert-Konvertierung [conv.lval]

1 - [...] Wenn das Objekt, auf das sich der Gl-Wert bezieht, [...] nicht initialisiert ist, hat ein Programm, das diese Konvertierung erfordert, ein nicht definiertes Verhalten.


//^L.

Hier ^List das Formular-Feed-Zeichen, das Teil des Basiszeichensatzes ist. 4 Zeichen (pro 2.2: 2 ist kein Zeilenumbruch erforderlich). Undefiniertes Verhalten ist per

2.8 Kommentare [lex.comment]

1 - Wenn in einem //Kommentar im [a- Stil] ein Formular-Feed oder ein vertikales Tabulatorzeichen enthalten ist , dürfen nur Leerzeichen zwischen dem Kommentar und der neuen Zeile angezeigt werden, die den Kommentar beendet. Es ist keine Diagnose erforderlich.


der zweite ist nicht undefiniert. Es kann die for-Schleife ohne Probleme optimieren. Das ist kein undefiniertes Verhalten.
Rubenvb

3
@rubenvb stackoverflow.com/questions/3592557/… - Immer wenn der Standard sagt "der Compiler kann P annehmen", wird impliziert, dass ein Programm mit der Eigenschaft nicht-P eine undefinierte Semantik hat .
Ecatmur

Der Compiler kann jedoch auch keine Nebenwirkungen annehmen, wenn Kopierkonstruktoren entfernt werden.
Rubenvb

@rubenvb, weil dieser spezielle Fall ausdrücklich erwähnt wird.
R. Martinho Fernandes

1
@BogdanAlexandru Ihr eingebettetes Projekt hat undefiniertes Verhalten. Das bedeutet, dass es möglicherweise wie erwartet funktioniert, aber wenn Sie Ihren Compiler aktualisieren, verhält es sich anders.
Ecatmur

5
\u\
0000

Dies hat acht Zeichen und ein undefiniertes Verhalten gemäß §2.2 / 1.

Jede Instanz eines Backslash-Zeichens ( \), unmittelbar gefolgt von einem neuen Zeilenzeichen, wird gelöscht, wodurch physische Quellzeilen zu logischen Quellzeilen gespleißt werden. Nur der letzte Backslash auf einer physischen Quellleitung kann Teil eines solchen Spleißes sein. Wenn als Ergebnis eine Zeichenfolge erzeugt wird, die der Syntax eines universellen Zeichennamens entspricht, ist das Verhalten undefiniert.


Dies ist kein & "Programm". Ein Programm hat eine main.
Rubenvb

@rubenvb Probieren Sie es auf Hell ++. Es hat undefiniertes Verhalten, kann also ein Programm ohne ein sein main. Es ist schwierig, Regeln durchzusetzen, wenn Sie nach einem Programm fragen, dem keine Regeln folgen müssen (das bedeutet UB!).
R. Martinho Fernandes

3
Basierend auf dem Wortlaut der Frage denke ich, dass dies qualifiziert ist - es wird nur nach dem kürzesten "Code" gefragt, der UB anzeigt. Basierend auf dem "ausführbaren" im Kommentar denke ich, dass die Absicht jedoch das kürzeste Programm war , das Ihren Code ausschließen würde, da gemäß §3.6.1 / 1: "Ein Programm muss eine globale Funktion namens main enthalten, Das ist der festgelegte Start des Programms. " Als solches ist das main, was du hast, schlecht geformt.
Jerry Coffin

1
@ JerryCoffin Er verwendet eine freistehende Umgebung, in der keine Hauptleitung erforderlich ist. Sie haben den Rest von §3.6.1 / 1 bequemerweise weggelassen, der besagt: "Es ist implementierungsdefiniert, ob ein Programm in einer freistehenden Umgebung erforderlich ist, um eine Hauptfunktion zu definieren." Dies ist ein gültiges Programm ("gültig", da es laut Ihrem Argument ein "Programm" ist).
David

Dang, bin gerade hergekommen, um das zu bringen. +1
Columbo

2
#include. /*Imagine a new-line right after the dot*/

§ 16.2 / 4:

Eine Vorverarbeitungsanweisung des Formulars

             #include  pp-tokens new-line

(das nicht mit einem der beiden vorherigen Formulare übereinstimmt) ist zulässig. [..] Wenn die nach allen Ersetzungen resultierende Direktive nicht mit einer der beiden vorherigen Formen übereinstimmt, ist das Verhalten undefiniert.


Wird es nicht gleich analysiert, wenn Sie das Leerzeichen vor dem Punkt entfernen?
Feersum

@feersum Ja. Das ändert nichts an der Idee, weshalb ich sie vermieden habe, um die Lesbarkeit zu verbessern, aber ich denke, sie dient dem Punkt der Frage, um zu veranschaulichen, dass der Raum weggelassen werden kann. Vielen Dank!
Columbo

2
int main(){int i=1>>-1;}

Erläuterung:

C ++ 98 und C ++ 11 §5.8 / 1 geben beide an, dass

Das Verhalten ist undefiniert, wenn der rechte Operand negativ ist oder größer oder gleich der Länge in Bits des heraufgestuften linken Operanden ist.


3
Ist auf einem 32-Bit-System die Länge in Bits nicht inttypisch 32? Das Ändern der RHS der Verschiebung auf -1ist die gleiche Anzahl von Zeichen und hängt nicht von ganzzahligen Größen ab
ardnew

1

Wenn man Wikipedia glauben will, hier ein paar:

Das Ändern von Zeichenfolgen soll undefiniertes Verhalten verursachen. Es hat immer für mich funktioniert.

int main(int c,char*v){v[0]='.';}

Eine nicht ungültige Funktion ohne Rückgabe verursacht undefinierte Rückgabewerte.

int a(){}
int main(){return a();}

Die Division (von int?) Durch Null ist angeblich undefiniert. Ich weiß nur, dass es abstürzt.

int main(int c){c/0;}

Dies sind keine rechtlichen Code-Schnipsel. Main muss zumindest als definiert werden int main(){}.
Rubenvb

Verdammt, ich war mir sicher, dass es um C ging. Tut mir leid.
Shiona

1
@shiona der zweite Parameter sollte char **nicht sein char *. Sie ändern lediglich einen Teil eines Zeigerwerts. In der Tat argvist garantiert sicher modifizierbar.
Oldrinb

Der Standard erlaubt, dass String- Literale schreibgeschützt sind, so viele Implementierungen tun dies. Es ist richtig char *argv[], keine constQualifikanten zu haben. Sie könnten abstürzen, indem Sie mitint main(){char *v="";*v=1;}
Peter Cordes

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.