Wenn der Wert einer nicht initialisierten Variablen den Wert eines Ausdrucks nicht beeinflussen sollte, ist es immer noch UB?

8

Dies ist eine Fortsetzung von eine Diskussion , die ich denke verdient eine eigene Frage.

Grundsätzlich ist das Ergebnis undefiniert?

%Vor%

Hier gibt es zwei Argumente für den gesunden Menschenverstand:

  1. Mathematisch gesprochen sollte der Wert von x unabhängig vom Wert von y 1 sein.
  2. Wegen des Kurzschlusses wird x sowieso nie ausgewertet.

Aber das Gegenargument ist, dass wir einen Ausdruck haben, der eine nicht initialisierte Variable beinhaltet, also sind alle Wetten (theoretisch) ausgeschaltet.

Wenn der Wert einer nicht initialisierten Variablen möglicherweise das Ergebnis eines Ausdrucks nicht beeinflussen kann, ist es dann "sicher"? z.B.:

%Vor%

Üblicher Haftungsausschluss: Natürlich befürworte ich nicht, jemals Code wie diesen zu schreiben.

    
Oliver Charlesworth 01.09.2011, 11:18
quelle

4 Antworten

8

In C ist es undefiniertes Verhalten, den Wert eines Objekts mit automatischer Speicherdauer zu verwenden, während es unbestimmt ist. (J.2, informativ), aber es ist OK für Variablen mit automatischer Speicherdauer einen unbestimmten Wert zu halten.

Ein Ausdruck kann nur dann seinen Wert verwenden, wenn er ausgewertet wird, und gemäß 6.5.12 (Logischer ODER-Operator) wird der zweite Operand nicht ausgewertet (geschweige denn seinen Wert verwendet), wenn der erste Operand ungleich 0 vergleicht.

    
Charles Bailey 01.09.2011, 11:44
quelle
6

Disclaimer: Ich dachte, die Frage war auch für C ++. Anscheinend ist es nur für C. Ich spreche nicht C-Standard, aber ich glaube, dass meine Antwort auch für C gilt, obwohl ich verschiedene Termologie verwende. %Vor%

ist gut definiert, weil x einfach nicht ausgewertet wird - Garantie der Kurzschlussauswertung von ||.

%Vor%

ruft undefined Behavior auf, weil x ausgewertet wird und eine lvalue-to-rvalue-Konvertierung stattfindet . Wenn diese Konvertierung nicht stattgefunden hat, wäre das Verhalten gut definiert, zum Beispiel:

%Vor%

Hier wird auch x ausgewertet, aber es findet keine lvalue-to-rvalue-Konvertierung statt, also ist es definiert.

    
Armen Tsirunyan 01.09.2011 11:22
quelle
2

Bezüglich y = x - x; ist ein Worst-Case-Szenario zu beachten, dass eine nicht initialisierte Variable einen Trap-Wert enthalten könnte.

Sie können sich nicht darauf verlassen, dass ein Optimierer erkennt, dass x - x nicht wirklich vom Wert von x abhängt, und daher kann die Implementierung sicher den Wert von x bei der Auswertung verwenden x - x , und es wird in der abstrakten Maschine verwendet.

Wenn es sich also um einen Trap-Wert handelt, haben Sie einen Hardwarefehler oder was auch immer die Implementierung macht, wenn sie auffängt. UB jedenfalls.

Ich erinnere mich, dass ein System, das ich verwendete, zusätzliche Garantien über das Verhalten von unbestimmten Werten gab. Es besagt, dass die Verwendung eines unbestimmten Wertes nicht explodieren würde, aber auch nicht so, als ob der Wert irgendein tatsächlicher Wert des Typs wäre. Also, x-x würde zu einem anderen unbestimmten Wert führen, nicht notwendigerweise 0. Dies ist eigentlich weniger als Trapping nützlich, da es den Programmierfehler für die spätere Verwendung speichert, wenn Sie es am wenigsten erwarten, aber AFAIK ist es völlig konform, da Verhalten nicht durch den Standard definiert ist.

    
Steve Jessop 01.09.2011 12:08
quelle
1
  

Grundsätzlich ist das Ergebnis undefiniert?

     

int x; int y = 1 || x;

Nein! x wird niemals verwendet / ausgewertet .

int y = x - x; ruft UB auf.

    
Prasoon Saurav 01.09.2011 11:24
quelle