Sollte der Bedingungsoperator alle Argumente auswerten?

8

Wenn Sie dies schreiben:

%Vor%

Der Microsoft Visual Studio 2005 64-Bit-Compiler kam mit

%Vor%

Während Sie und ich klar sehen können, dass ein div-by-zero niemals passieren wird ...

Oder ist es?

    
xtofl 24.11.2009, 08:00
quelle

8 Antworten

4

Es ist ein offensichtlicher Fehler, außer Zweifel.

Die Absicht der Warnung ist NICHT, über alle Unterteilungen in einem Programm zu warnen. Das wäre viel zu laut in irgendeinem vernünftigen Programm. Stattdessen besteht die Absicht darin, Sie zu warnen, wenn Sie ein Argument überprüfen müssen. In diesem Fall haben Sie das Argument überprüft. Daher sollte der Compiler dies bemerkt haben und den Mund halten.

Die technische Implementierung eines solchen Features erfolgt durch die Kennzeichnung von Variablen in Code-Zweigen mit bestimmten Attributen. Eines der gebräuchlichsten Attribute ist der Dreizustand "Ist Null". Vor der Verzweigung ist arg eine externe Variable und arg [[Isnull]] ist unbekannt. Aber nach der Überprüfung auf arg gibt es zwei Zweige. Im ersten Zweig ist arg [[Isnull]] wahr. Im zweiten Zweig ist arg [[Isnull]] falsch.

Wenn es darum geht, durch Nullzeiger und Nullzeiger Warnungen zu generieren, sollte das Attribut [[IsNull] überprüft werden. Wenn dies der Fall ist, haben Sie eine schwerwiegende Warnung / einen Fehler. Wenn sie nicht bekannt sind, sollten Sie die oben gezeigte Warnung generieren - ein potenzielles Problem, über das hinaus, was der Compiler beweisen kann. In diesem Fall ist das Attribut [[isNull]] jedoch False. Der Compiler durch die gleiche formale Logik wie Menschen weiß, dass es kein Risiko gibt.

Aber woher wissen wir, dass der Compiler intern ein solches Attribut [[Isnull]] verwendet? Erinnern Sie sich an den ersten Absatz: Ohne ihn müsste er entweder immer oder nie warnen. Wir wissen, dass es manchmal warnt, daher muss ein Attribut [[IsNull]] vorhanden sein.

    
MSalters 26.11.2009, 15:18
quelle
11

Der Compiler ist nicht in der Lage, alle Code-Pfade statisch zu analysieren und alle Möglichkeiten jederzeit zu berücksichtigen. Theoretisch kann die vollständige Analyse eines Programmverhaltens, indem man einfach in den Quellcode schaut, eine Lösung für das Anhalten des Problems liefern, die unentscheidbar ist. Compiler haben eine begrenzte Anzahl von statischen Analyse-Regeln, um Regeln zu erkennen. Der C ++ - Standard erfordert nicht, dass der Compiler solche Warnungen ausgibt, also nein. Es ist kein Fehler. Es ist mehr wie eine nicht vorhandene Funktion.

    
Mehrdad Afshari 24.11.2009 08:04
quelle
7

Nein, der bedingte Operator wertet beide Argumente nicht aus. Ein Potential dividiere durch Null, wenn ein Compiler eine solche Sache erkennen kann, wird jedoch typischerweise gemeldet. Es ist nicht umsonst, dass der Standard ~ 2 Seiten benötigt, um das Verhalten dieses Operators zu beschreiben.

Von N-4411:

  

5.16 Bedingter Operator

     

1 Gruppe für bedingte Ausdrücke   rechts nach links. Der erste Ausdruck ist   Kontextuell in Boole umgewandelt   4). Es wird ausgewertet und wenn es wahr ist,   das Ergebnis der Bedingung   Ausdruck ist der Wert des zweiten   Ausdruck, sonst der der   dritter Ausdruck. Nur einer der   zweiter und dritter Ausdruck ist   bewertet. Jede Wertberechnung und   Nebeneffekt mit dem ersten verbunden   Der Ausdruck ist vor jedem sequenziert   Wertberechnung und Nebeneffekt   mit dem zweiten oder dritten verbunden   Ausdruck.

Beachten Sie auch:

  

3 Ansonsten, wenn die zweite und dritte   Operand haben verschiedene Arten und   entweder hat (möglicherweise cv-qualifiziert)   Klassentyp, ein Versuch wird gemacht   wandle jeden dieser Operanden in den   Art des anderen.

Das von Ihnen zitierte Beispiel hat denselben Typ für den zweiten und den dritten Ausdruck - seien Sie versichert, nur der erste wird ausgewertet.

    
dirkgently 24.11.2009 08:05
quelle
3

Der Code für die Division wird generiert, daher die Warnung. aber die Verzweigung wird nie genommen, wenn arg 0 ist, also ist es sicher.

    
Adrien Plisson 24.11.2009 08:05
quelle
3

operator == für Fließkommazahlen ist unsicher (d. h. Sie können ihm aufgrund von Rundungsproblemen nicht vertrauen). In diesem speziellen Fall ist es tatsächlich sicher, so dass Sie die Warnung ignorieren können, aber der Compiler wird eine solche Analyse nicht basierend auf einem Operator durchführen, dessen Ergebnisse im allgemeinen Fall etwas unvorhersehbar sind.

    
Gorpik 24.11.2009 08:12
quelle
3

Der Bedingungsoperator sollte nicht alle Argumente auswerten. Aber ich glaube, du könntest arg fast gleich 0 nehmen, also wird arg == 0.0 false sein, aber 1./arg wird "Division durch Null" ergeben. Also denke ich, dass die Warnung hier nützlich ist.

Übrigens gibt Visual C ++ 2008 keine solche Warnung.

    
Kirill V. Lyadvinsky 24.11.2009 09:11
quelle
0

Zusätzlich zu den anderen Kommentaren: Die Warnung wird vom Compiler generiert, der tote Zweig wird vom Optimierer entfernt, der später ausgeführt wird - möglicherweise sogar in der Verknüpfungsphase.

Also nein, es ist kein Fehler. Die Warnung ist ein zusätzlicher Service, der vom Compiler bereitgestellt wird und nicht vom Standard vorgeschrieben wird. Es ist ein unglücklicher Nebeneffekt der Compiler / Linker-Architektur.

    
peterchen 24.11.2009 12:38
quelle
0

Sie können die Warnung möglicherweise mithilfe des Microsoft-spezifischen Schlüsselworts __assume vermeiden. Ich bin mir nicht sicher, ob Sie es mit dem Bedingungsoperator verknüpfen können. Sonst etwas wie

%Vor%

kann einen Versuch wert sein. Oder, natürlich, stumm die Warnung während dieser Funktion mit der entsprechenden #pragma .

    
jalf 26.11.2009 15:37
quelle

Tags und Links