Zugriff auf inaktiv union-Mitglied und Undefiniertes Verhalten?
War ich unter dem Eindruck, dass der Zugriff auf eine union
Mitglied anderer als der Letzte gesetzt wird UB, aber ich kann nicht scheinen zu finden, eine solide Referenz (eine andere als Antworten zu fordern, es ist UB, aber ohne jegliche Unterstützung von der standard).
So, ist es Undefiniertes Verhalten?
C99 (und ich glaube, dass C++11) explizit zulassen, Typ-Zweideutigkeiten mit den Gewerkschaften. Also ich denke, es fällt unter "implementation defined" Verhalten.
Ich habe es mehrmals zum konvertieren von einzelnen int zu char. Also, ich definitiv weiß, es ist nicht undefiniert. Ich habe es auf der Sun CC compiler. Also, es könnte immer noch compiler-abhängig.
Klar, man weiß nicht, was es bedeutet, für das Verhalten undefiniert. Die Tatsache, dass es schien, für Sie zu arbeiten, in einigen Instanz widerspricht nicht seiner undefinededness.
Verwandte: Zweck von Gewerkschaften in C und C++
der blog-Beitrag, den Sie verlinken, ist sehr spezifisch in Bezug auf C99; diese Frage ist tagged nur für C++.
Ich habe es mehrmals zum konvertieren von einzelnen int zu char. Also, ich definitiv weiß, es ist nicht undefiniert. Ich habe es auf der Sun CC compiler. Also, es könnte immer noch compiler-abhängig.
Klar, man weiß nicht, was es bedeutet, für das Verhalten undefiniert. Die Tatsache, dass es schien, für Sie zu arbeiten, in einigen Instanz widerspricht nicht seiner undefinededness.
Verwandte: Zweck von Gewerkschaften in C und C++
der blog-Beitrag, den Sie verlinken, ist sehr spezifisch in Bezug auf C99; diese Frage ist tagged nur für C++.
InformationsquelleAutor Luchian Grigore | 2012-07-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Verwirrung ist, dass C explizit erlaubt Typ-Zweideutigkeiten durch eine union, in der Erwägung, dass C++ (c++11) hat keine solche Erlaubnis.
Die situation mit C++:
C++ später hat die Sprache, welche die Verwendung der Gewerkschaften mit
struct
s mit gemeinsamen anfangs-Sequenzen; dies bedeutet jedoch nicht zulassen, Typ-Zweideutigkeiten.Um zu bestimmen, ob union Typ-Zweideutigkeiten ist erlaubt in C++, die wir haben, um weiter zu suchen. Daran erinnern, dass c99 ist eine normative Referenz für C++11 (und C99 hat ähnliche Sprache C11 zulassen union-Typ-Zweideutigkeiten):
Wird es besonders interessant, wenn wir Lesen
Also für einen primitiven Typ (ipso facto hat triviale Initialisierung), die in einer union, die Lebensdauer des Objekts umfasst mindestens die Lebensdauer von der union selbst. Dies ermöglicht uns zum aufrufen
Unter der Annahme, dass der Betrieb sind wir interessiert, ist die Typ-Zweideutigkeiten, d.h. der Wert einer nicht-aktives Gewerkschaftsmitglied, und da gemäß der obigen, dass wir eine gültige Referenz auf das Objekt bezeichnet, um Sie von diesem Mitglied, dass die operation lvalue-rvalue-Konvertierung:
Dann stellt sich die Frage, ob ein Objekt, ein nicht-aktives Gewerkschaftsmitglied initialisiert Speicher für die aktiven Gewerkschaftsmitglieder. So weit wie ich kann sagen, dies ist nicht der Fall, und so, obwohl, wenn:
char
array Speicher und zurück (3.9:2), oderden Zugang zu einer union von einem nicht-aktiven Mitglied definiert ist und definiert ist, zu Folgen, das Objekt und der Wert der Repräsentation, Zugang auch ohne eine der oben genannten interpositions ist Undefiniertes Verhalten. Dies hat Konsequenzen für den Optimierungen dürfen durchgeführt werden, wenn ein solches Programm, wie die Umsetzung kann natürlich davon ausgehen, dass Undefiniertes Verhalten tritt nicht auf.
Ist, obwohl wir sind legitim Formular ein lvalue auf einen nicht-aktiv-union-Mitglied (das ist der Grund, warum die Zuordnung zu einem nicht-aktiven Mitglied, ohne Aufbau ist ok), es wird als nicht initialisiert werden.
3.8/1 sagt, dass die Lebensdauer eines Objekts endet, wenn der Speicher wiederverwendet. Das zeigt mir, dass ein nicht-aktives Mitglied in einer union Leben beendet hat, weil sein Speicher wurde wiederverwendet für die aktive Mitgliedschaft. Das würde bedeuten, dass Sie zu beschränkt sind, wie Sie das Element verwenden (3.8/6).
guter Punkt, aber wenn es trivial Initialisierung dann ist die Lebensdauer beginnt sofort wieder, oder wenn die nicht-aktive member zugegriffen wird ( " Speicher mit der korrekten Ausrichtung und Größe für Typ
T
ist gewonnen).Unter dieser interpretation dann jedes bit des Speichers gleichzeitig enthält Gegenstände aller Arten, die trivial initiallizable haben und entsprechende Ausrichtung... Also dann macht das Leben einer nicht-trivial initiallizable geben Sie beenden sofort Ihre Lagerung wiederverwendet wird, der für all diese Typen (und nicht neu starten, da Sie nicht trivial initiallizable)?
Der Wortlaut 4.1 ist ganz und gar gebrochen und hat seit umgeschrieben wurde. Es nicht zulässig, alle Arten von absolut gültigen Dinge: es unzulässig, benutzerdefinierte
memcpy
Implementierungen (Zugriff auf Objekte mitunsigned char
lvalues), es nicht erlaubte Zugriffe zu*p
nachint *p = 0; const int *const *pp = &p;
(obwohl die implizite Konvertierung vonint**
zuconst int*const*
gültig ist), ist es nicht zulässig, auch Zugriff aufc
nachstruct S s; const S &c = s;
. CWG Problem 616. Hat die neue Formulierungen zulassen? Es gibt auch [basic.lval].InformationsquelleAutor ecatmur
Den C++11 standard, sagt es auf diese Weise
Wenn nur ein Wert gespeichert ist, wie kann Sie Lesen, anderen? Es ist einfach nicht da.
Den gcc-Dokumentation listet diese unter Umsetzung definiert Verhalten
darauf hinweist, dass dies nicht erforderlich ist durch den C-standard.
2016-01-05: Durch die Kommentare, die ich war mit C99 Defect Report #283 wodurch ein ähnlicher text als Fußnote der C-standard-Dokument:
Nicht sicher, ob es klärt viel, obwohl, wenn man bedenkt, dass eine Fußnote ist nicht normativ für den standard.
Es ist ziemlich klar, was aktiv bedeutet, "das heißt, der Wert von mindestens einer der nicht-statischen Daten-member können gespeichert werden, in einer union zu jeder Zeit."
Ja, es gibt. Es gibt unendliche Menge der Fälle, die der standard nicht (und kann nicht) - Adresse. (C++ ist eine Turing-vollständige VM-es ist also unvollständig.) So what? Es erklärt, was "aktiv" bedeutet, beziehen sich auf das obige Zitat, nach dem "das ist".
Unterlassung der expliziten definition von Verhalten wird auch unberücksichtigt Undefiniertes Verhalten nach den Begriffsbestimmungen Abschnitt.
Das ist UB für einen anderen Grund - es verletzt strict-aliasing.
InformationsquelleAutor Bo Persson
Ich denke, der nächste standard kommt zu sagen, es ist Undefiniertes Verhalten ist, wo Sie definiert das Verhalten für eine union mit einem gemeinsamen anfangs-Sequenz (C99, §6.5.2.3/5):
C++11 gibt ähnliche Voraussetzungen/Genehmigung §9.2/19:
Obwohl weder die Staaten es direkt, diese tragen beide eine starke Implikation, dass die "Inspektion" (Lesen) ein Mitglied ist "erlaubt" nur, wenn 1) es ist (teilweise) das Mitglied zuletzt geschrieben, oder 2) ist Teil eines gemeinsamen anfangs-Sequenz.
Ist das nicht eine direkte Aussage, dass zu tun, sonst Undefiniertes Verhalten, aber die nächsten von denen ich weiß.
Ja und Nein. Sie benötigen, um mit denen, wenn/wenn Sie sicher sein wollen, ob etwas fällt in diese Ausnahme-aber die eigentliche Frage hier ist, ob etwas, das deutlich außerhalb der Ausnahme wirklich gibt, UB. Ich denke, das ist stark genug, hier angedeutet, um die Absicht klar, aber ich glaube nicht, dass es immer direkt angegeben.
Dieses "gemeinsame" initial sequence" Sache, könnte nur gespeichert haben 2 oder 3 meiner Projekte aus der Rewrite-Bin. Ich war wütend, wenn ich lese zuerst über die meisten Zweideutigkeiten verwendet, der
union
s wird nicht definiert, da würde ich den Eindruck von einer bestimmten blog, dass das OK war, und baute mehrere große Strukturen und Projekte um. Jetzt habe ich glaubst ich könnte in Ordnung sein, nachdem alle, da meinunion
s enthalten Klassen mit dem gleichen Typen an der frontIch glaube, Sie waren ein fingerzeig auf die gleiche Frage wie ich: was, wenn unsere
union
enthält z.B. einuint8_t
und einclass Something { uint8_t myByte; [...] };
- ich würde vermuten, dass dieser VORBEHALT würde auch hier gelten, aber es ist formuliert sehr bewusst, dass nur fürstruct
s. Zum Glück bin ich schon mit diesen anstelle von roh-primitive :ODer C-standard zumindest Art von Abdeckungen, die Frage: "Ein Zeiger auf ein Struktur-Objekt, entsprechend umgewandelt, Punkte zu seinem ersten Mitglied (oder, wenn das Mitglied ist eine bit-Feld, dann auf die Einheit, in der es sich befindet), und Umgekehrt."
InformationsquelleAutor Jerry Coffin
Etwas, das noch nicht erwähnt von möglichen Antworten ist die Fußnote 37 in der Nummer 21 des Abschnitts 6.2.5:
Diese Anforderung scheint klar anzudeuten, dass Sie müssen nicht schreiben, dass in einem Mitgliedstaat und Lesen in einer anderen. In diesem Fall ist es möglicherweise nicht definiertes Verhalten durch einen Mangel an Spezifikation.
Viele Implementierungen dokumentieren Ihre storage-Formate und layout-Regeln. Eine solche Vorgabe würde in vielen Fällen bedeuten, was die Wirkung des Lesens Speicher eines Typs und schreiben als eine andere wäre in der Abwesenheit von Regeln sagen Compiler nicht haben, um tatsächlich nutzen Ihre definierte Speicher-format, außer, wenn die Dinge werden gelesen und geschrieben mit Zeiger, der ein Zeichen geben.
InformationsquelleAutor mpu
Ich gut erklären dies mit einem Beispiel.
angenommen, wir haben folgende union:
Ich wohl davon ausgehen, dass
sizeof(int)
gibt 4, und dasssizeof(short)
gibt 2.wenn Sie schreiben
union A a = {10}
dass nun erstellen Sie eine neue var von Typ A in in Sie setzen den Wert 10.Ihre Speicher sollte so Aussehen: (beachten Sie, dass alle union-Mitglieder bekommen den gleichen Ort)
als Sie sehen konnte, der Wert einer.x ist 10, der Wert einer.yEins ist 10, und der Wert einer.y[0] ist 0.
nun, was wohl passiert, wenn ich dies tun?
unserer Erinnerung wird wie folgt Aussehen:
damit wird der Wert einer.x 2424842 (in dezimal).
nun, wenn Sie Ihre Hochzeit hat ein float oder double, wird der memory-Karte wohl mehr ein Durcheinander, wegen der Art, Sie speichern die genauen zahlen.
mehr Informationen, die Sie bekommen konnte in hier.
InformationsquelleAutor elyashiv