Verleiht der Zugriff auf ein deklariertes nichtflüchtiges Objekt über einen flüchtigen Verweis / Zeiger diesen Zugriffen flüchtige Regeln?

Dies wird ein langer Weg sein, um ihn zu kontextualisieren und so viele Informationen wie möglich bereitzustellen. Ich muss mich durch verschiedene Links und Zitate schlängeln - wie es oft der einzige Weg ist, wenn wir das C / C ++ - Standard-Kaninchenloch betreten. Wenn Sie bessere Zitate oder andere Verbesserungen an diesem Beitrag haben, lassen Sie es mich bitte wissen. Aber um es vorweg zusammenzufassen,ie können @@ schu zwol für mich das posten; -) und das Ziel ist es, die Wahrheit aus zwei Aussagen zu finden:

Führen Sie die C- und (durch Import; siehe Kommentare) C ++ - Standards erfordern, dass Zugriffe übervolatile * odervolatile & muss auf ein Objekt verweisen, das ursprünglich als @ deklariert wurvolatile um zu habenvolatile Semantik?Oder greift auf ein Nicht-@ volatile -qualifiziertes Objekt durch einvolatile Zeiger / Verweis ausreichend / soll bewirken, dass sich die Zugriffe so verhalten, als ob das Objekt als @ deklariert worden wävolatile?

Und so oder so, wenn (wie es scheint) der Wortlaut im Vergleich zu der Absicht etwas mehrdeutig ist -können wir das klarstellen in den Standards selbst?

Die 1. dieser sich gegenseitig ausschließenden Interpretationen wird häufiger gehalten, und das ist nicht ganz unbegründet. Ich hoffe jedoch zu zeigen, dass es eine erhebliche Menge von "begründeten Zweifeln" zugunsten der zweiten gibt - insbesondere, wenn wir auf einige frühere Passagen in den Rational and WG Papers zurückgreifen.


Accepted wisdom: das referenzierte Objekt selbst muss als @ deklariert worden sevolatile

Gestern beliebte FrageIst die Definition von "volatile" diese volatile, oder hat GCC einige Standardkonformitätsprobleme? entstand durch die Annahme einesvolatile Referenz würde verleihenvolatile Verhalten auf einem Nichtvolatile referent - aber festgestellt, dass dies nicht oder in unterschiedlichem Maße und auf unvorhersehbare Weise der Fall war.

Die akzeptierte Antwort kam zunächst zu dem Schluss, dass nur der deklarierte Typ des Referenten von Bedeutung ist. Dies und die meisten Kommentare schienen zu einer Übereinstimmung zu führen, dass äquivalente Prinzipien im Spiel sind, wie wir sie für @ gut kenneconst: das Verhalten wäre nurvolatile (oder überhaupt definiert), wenn die Referenz das gleiche @ hLebenslau -Qualifikation als referiertes Objekt:

Das Schlüsselwort in dieser Passage ist Objekt.volatile sig_atomic_t flag; ist ein flüchtiges Objekt.*(volatile char *)foo ist nurein Zugriff über einen flüchtig qualifizierten Wert und der Standard erfordert keine speziellen Effekte.. - zwol

Diese Interpretation scheint ziemlich weit verbreitet zu sein, wie aus den Antworten auf diese ähnliche, aber hoffentlich nicht doppelte Frage hervorgeht:Voraussetzungen für das Verhalten des Zeigers auf ein flüchtiges Objekt Aber auch dort herrscht Unsicherheit: Direkt nach der Antwort 'Nein' steht dann 'Vielleicht'! Wie auch immer ... lasst uns im Standard nachsehen, worauf die Nein basieren.


Was der Standard sagt ... oder nicht

C11, N1548, §6.7.3: Während es klar ist, dass es UB ist, auf ein Objekt zuzugreifen definiert mit volatile oderconst tippe über einen Zeiger, der das genannte Qualifikationsmerkmal nicht teilt ...

6 Wenn versucht wird, ein mit einem @ definiertes Objekt zu ändeconst -qualifizierter Typ durch Verwendung eines lWertes mit nichtconst -qualifizierter Typ, das Verhalten ist undefiniert. Wenn versucht wird, auf @ zu verweis ein mit einem @ definiertes Objevolatile -qualifizierter Typ durch Verwendung eines lvalue mit non-volatile-qualifizierter Typ, das Verhalten ist undefiniert. (133)

... der Standard scheint das umgekehrte Szenario nicht explizit zu erwähnen, nämlich fürvolatile. Bei der Zusammenfassung vonvolatile und Operationen darauf, spricht es jetzt über ein Objekt, dasha volatile -qualifizierter Typ:

7 EinObjekt, das @ hvolatile -qualifizierter Typ kann auf eine der Implementierung unbekannte Weise modifiziert werden oder andere unbekannte Nebenwirkungen haben. Daher muss jeder Ausdruck, der sich auf ein solches Objekt bezieht, streng nach den Regeln der abstrakten Maschine bewertet werden, wie in 5.1.2.3 beschrieben. Ferner muss an jedem Sequenzpunkt der zuletzt im Objekt gespeicherte Wert mit dem von der abstrakten Maschine vorgegebenen Wert übereinstimmen, sofern er nicht durch die zuvor genannten unbekannten Faktoren geändert wurde. (134) Was bedeutet ein Zugriff auf ein Objekt mitvolatile -qualifizierter Typ ist implementierungsdefiniert.

Sollen wir annehmen, dass "hat" gleichbedeutend ist mit "wurde definiert mit"? odercan "has" auf eine Kombination aus Objekt- und Referenzqualifizierern verweisen?

Ein Kommentator fasste das Problem mit dieser Formulierung gut zusammen:

Von n1548 §6.7.3 ¶6 Der Standard verwendet den Ausdruck "Objekt mit einem flüchtig qualifizierten Typ definiert", um es von "Wert mit einem flüchtig qualifizierten Typ" zu unterscheiden. Es ist bedauerlich, dass dieses mit "versus" lvalue "definierte" Objekt "nicht weitergegeben wird, und der Standard verwendet dann" Objekt mit flüchtig qualifiziertem Typ "und sagt" was den Zugriff auf ein Objekt mit flüchtig qualifiziertem Typ ausmacht " ist implementierungsdefiniert "(was aus Gründen der Klarheit" lvalue "oder" object defined with "bedeuten könnte). Naja. -Dietrich Epp

Paragraph 4 desselben Abschnitts scheint seltener zitiert zu werden, könnte aber durchaus relevant sein, wie wir im nächsten Abschnitt sehen werden.


Vernünftiger Zweifel: Ist / War einvolatile Zeiger / Referenz zur Verleihung vonvolatile Semantik auf seine Dereferenzierung?

Die vorgenannte Antwort enthält einen Kommentar, in dem der Autor eine frühere Aussage des Ausschusses zitiert, die Zweifel an der Idee „Verweis muss mit Verweis übereinstimmen“ aufwirft:

Interessanterweise gibt es dort einen Satz C99 Begründung fürvolatile] das bedeutet, dass der Ausschussgemein zum*(volatile T*)x um den Zugriff auf @ zu erzwingx als flüchtig eingestuft werden; Dies wird jedoch durch den tatsächlichen Wortlaut der Norm nicht erreicht. - zwol

Wir können ein bisschen mehr Informationen zu diesem Teil der Begründung finden, aus dem 2. oben erwähnten Thread:Voraussetzungen für das Verhalten des Zeigers auf ein flüchtiges Objekt

Auf der anderen Seite,dieser Beitra Zitate aus dem 6.7.3 des Grundgedankens für internationale Standards - Programmiersprachen - C:

Eine Umwandlung eines Werts in einen qualifizierten Typ hat keine Auswirkung. Die Qualifikation (z. B. flüchtig) kann keine Auswirkung auf den Zugriff haben, da sie vor dem Fall stattgefunden hat.Wenn auf ein nichtflüchtiges Objekt unter Verwendung der flüchtigen Semantik zugegriffen werden muss, besteht die Technik darin, die Adresse des Objekts in den entsprechenden Zeiger auf den qualifizierten Typ umzuwandeln und diesen Zeiger dann dereferenzieren.

philipxy

Und vonthat Bytes thread, wir beziehen uns auf C99 s6.7.3 p3 - a.k.a. C11s p4 - und diese Analyse:

Der betreffende Absatz steht kurz vor Abschnitt 6.7.3.1 im Begründungstext. Wenn Sie auch aus dem Standarddokument selbst zitieren müssen, geben Sie @ a 6.7.3 p3:

Die mit qualifizierten Typen verknüpften Eigenschaften sind nur für lvalues-Ausdrücke von Bedeutung.

Der Ausdruck(volatile WHATEVER) non_volatile_object_identifier istnich ein lWert, daher ist das Qualifikationsmerkmal 'volatile' bedeutungslos.

Umgekehrt ist der Ausdruck* (volatile WHATEVER *) & non_volatile_object_identifier ist an lvalue (es kann auf der linken Seite einer Zuweisungsanweisung stehen), daher hat die Eigenschaft des 'volatile'-Qualifiers in diesem Fall die beabsichtigte Bedeutung.

Tim Rentsch

Da ist einseh spezifische Demonstration, die diese Idee unterstützt, unter besonderer Berücksichtigung der 1. verknüpften Frage inWG Paper N1381. Dies führte die Annexedmemset_s() um das zu tun, was das OP wollte - garantieren Sie das unbeabsichtigte Füllen des Speichers. Bei der Erörterung möglicher Implementierungen scheint die Idee zu stützen, dass bei der Angabe von Anforderungen ein @ verwendet wirvolatile Zeiger zum Ändern eines Nichtvolatile Objektsollt Code generieren basierend auf demqualifier des Zeigers, unabhängig von dem Objekt, auf das verwiesen wird ...

Plattformunabhängige 'Secure-Memset'-Lösung:
void *secure_memset(void *v, int c , size_t n) {
    volatile unsigned char *p = v;
    while (n--) *p++ = c;
    return v;
}

Dieser Ansatz verhindert, dass das Löschen des Speichers optimiert wird, undit sollte auf jeder standardkonformen Plattform funktionieren.

... und dass Compiler, die dies nicht tun, benachrichtigt werden ...

Es wurde kürzlich bemerkt, dassinige Compiler verletzen den Standard, indem sie das @ nicht immer einhaltevolatile Qualifier.


Wer hat Recht?

Das war anstrengend. Es gibt hier sicherlich viel Interpretationsspielraum, abhängig davon, welche Dokumente Sie gerade gelesen haben und welche nicht und wie Sie viele Wörter interpretieren, die nicht spezifisch genug sind. Es scheint klar, dass etwas nicht stimmt: entweder:

the Rationale und N1381 sind falsch oder willkürlich formuliert, odersie wurden ausdrücklich rückwirkend ungültig gemacht ... oderdie Norm ist falsch oder willkürlich formuliert.

Ich hoffe, dass wir das besser können als all die Unklarheiten und Spekulationen, die dies in der Vergangenheit umgaben - und eine schlüssigere Aussage machen können. Zu diesem Zweck wären weitere Quellen und Gedanken von Experten sehr willkommen.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage