Strikter Zeiger -Aliasing: Ist der Zugriff über einen "flüchtigen" Zeiger/Referenz eine Lösung?
-
24-10-2019 - |
Frage
Auf den Fersen ein spezifisches Problem, Ich würde gerne verstehen, ob es sich um eine richtige Lösung, eine Problemumgehung/Hack oder einfach falsch handelt.
Insbesondere habe ich Code neu geschrieben:
T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
...
Wie:
T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
...
mit einer volatile
Qualifikation zum Zeiger.
Nehmen wir einfach an, dass das behandeln T
wie int
in meiner Situation macht Sinn. Zugriff dies über a volatile
Referenzlöser Zeiger -Aliasing -Problem?
Als Referenz aus der Spezifikation:
Hinweis: Volatile ist ein Hinweis auf die Implementierung, um eine aggressive Optimierung des Objekts zu vermeiden, da der Wert des Objekts durch eine durch eine Implementierung nicht nachweisbare Mittel geändert werden kann. Siehe 1.9 für detaillierte Semantik. Im Allgemeinen sollen die Semantik von flüchtigem in C ++ gleich sein wie in C. - Endnote
BEARBEITEN:
Der obige Code hat mein Problem zumindest bei GCC 4.5 gelöst.
Lösung
Völlig kann Ihnen nicht helfen, ein undefiniertes Verhalten hier zu vermeiden. Also, wenn es mit GCC für Sie funktioniert, ist es Glück.
Nehmen wir an, T ist ein Pod. Dann ist der richtige Weg, dies zu tun
T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
…
Dort! Kein striktes Aliasing -Problem und kein Problem mit Gedächtnisausrichtungen. GCC behandelt sogar Memcpy als intrinsische Funktion (in diesem Fall wird kein Funktionsaufruf eingefügt).
Andere Tipps
Völlig kann Ihnen nicht helfen, ein undefiniertes Verhalten hier zu vermeiden.
Nun, alles in Bezug auf volatile
ist im Standard etwas unklar. Ich stimmte hauptsächlich mit Ihrer Antwort zu, aber jetzt möchte ich etwas nicht zustimmen.
Um zu verstehen was volatile
Mittel, der Standard ist für die meisten Menschen nicht klar, insbesondere einige Compiler -Autoren. Es ist besser zu denken:beim Benutzen volatile
(und nur wenn) C/C ++ ist ziemlich hoch auf hoher Stufe Montage.
Beim Schreiben an a volatile
LVALUE, der Compiler stellt ein Geschäft oder mehrere Speicher aus, wenn man nicht ausreicht (volatile
impliziert nicht atomar).
Beim Schreiben an a volatile
LVALUE, der Compiler stellt eine Last oder mehrere Last aus, wenn einer nicht ausreicht.
Wenn es keine explizite Last oder Speicher gibt, gibt der Compiler nur Anweisungen aus, die eine Last oder Speicher implizieren.
Sellibitze gab die beste Lösung: verwenden memcpy
für Bit -Neuinterpretationen.
Aber wenn alle Zugriffe auf eine Speicherregion mit erledigt sind volatile
lvalues, Es ist vollkommen klar, dass die strengen Aliasing -Regeln nicht gelten. Dies ist die Antwort auf Ihre Frage.