aliasing und alignment
-
cooky451 schrieb:
dot schrieb:
Placement new konstruiert ein Objekt, das ist alles. Wo genau hab ich denn geschrieben dass du damit auf definierte Art und Weise ein Objekt als von anderem Typ interpretieren kannst!?
**
Du hast geschrieben, dass dasEs geht darum, auf einen Speicherbereich so zuzugreifen "als wären es" [typ].
nicht geht.* Was macht placement new denn anderes? Es packt sich den Speicherbereich und du kannst hinterher drauf zugreifen, als wäre es [typ].
Ähm, Placement new erzeugt einfach ein Objekt, das wars. Und was das anbelangt ist dein Code mit placement new imo in Ordnung, du erzeugst dort eben einen neuen double, das wars. Aber du kannst nicht nachher auf irgendwas zugreifen als wäre es was anderes. Natürlich funktioniert das auf jeder mir bekannten Implementierung. Ob der Zugriff auf buf nach dem new in dem Fall undefiniert wäre weil es ein short[2] ist und wie das aussehen würde wenn es stattdessen ein char Array wäre, ist eine gute Frage. Aber ich würd nicht davon ausgehen dass man das als wohldefiniert betrachten kann. Natürlich wird es auf praktisch jedem System funktionieren, aber das tut der altbekannte union-Hack auch...
cooky451 schrieb:
Es geht darum einen Standardkonformen Weg zu finden - eventuell mit static_assert für Systeme auf denen es nicht geht. Aber mit der Voraussetzung: Es kompiliert, es funktioniert.
memcpy()...
-
dot schrieb:
memcpy()...
Wie gesagt, dann hat man auf Systemen auf denen man eigentlich nicht kopieren müsste die schlechtere Performance.
-
Und wo liegt das Problem, auf konkreten Implementierungen einfach konkretes, implementierungsabhängiges Verhalten auszunutzen, wenn das doch genau ist was du eigentlich tun willst!?
-
Nun, ich möchte einen standardkonformen Weg finden, der immer das Beste aus der jeweiligen Plattform holt. Ist das so schwer nachzuvollziehen?
-
Nein, es ist nicht schwer nachzuvollziehen. Aber auch wenn ich es nachvollziehen kann, so ändert das nix dran, dass es so einen Weg meines Wissens nach schlicht und einfach nicht gibt.
§3.10/10 sagt ausdrücklich, ganz klar, deutlich und unmissverständlich dass jeder Zugriff auf ein Objekt durch einen anderen Typ als den "richtigen" Typ des Objektes oder unsigned/signed char undefiniert ist. Was den Standard angeht war's das, end of story.
-
Auf Stack Overflow war irgendwo ein Beispiel, wo das ganze ohne lvalues gemacht wurde (in C) (Es ist ja nur für lvalues undefiniert). Würde das vlt in C++ auch gehen?
-
Wie willst du ohne lvalue auf ein Objekt zugreifen?
-
Stimmt, schreiben wird schwierig

-
lesen auch

-
http://stackoverflow.com/a/4935669 schrieb:
The following does not violate the aliasing rule, because it has no use of lvalues accessing different types anywhere
template<typename B, typename A> B noalias_cast(A a) { union N { A a; B b; N(A a):a(a) { } }; return N(a).b; } unsigned bar(float x) { return noalias_cast<unsigned>(x); }
-
Das ist laut Standard undefiniert:
ISO/IEC 14882:2011 schrieb:
In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
-
Can be stored. Aber da steht doch nichts von lesen, oder?
-
Aber was soll das bringen? Ist doch das gleiche wie memcpy, nur umständlicher.
-
pyhax schrieb:
http://stackoverflow.com/a/4935669 schrieb:
The following does not violate the aliasing rule, because it has no use of lvalues accessing different types anywhere
template<typename B, typename A> B noalias_cast(A a) { union N { A a; B b; N(A a):a(a) { } }; return N(a).b; } unsigned bar(float x) { return noalias_cast<unsigned>(x); }Clever. Evtl. zu clever, weil zwar die Aliasiang-Regel nicht verletzt wird. Andererseits aber der Standard mm.W. nirgendwo sagt, was denn nun das Ergebnis dieses Memberzugriffes sein soll (also am Ende doch UB) - außer dem Wert, der entstände, wenn es ein lvalue-Ausdruck wäre, der zu einem rvalue konvertiert wird (was in Hinblick auf Alisiang eben gerade nicht zulässig ist).
Die memcpy-Variante funktioniert wahrscheinlich auch nicht, jedenfalls scheint es in C recht explizit verboten zu sein (C99 6.5/6 6.5/7, den neuen Standard habe ich nicht).
-
pyhax schrieb:
Can be stored. Aber da steht doch nichts von lesen, oder?
Das impliziert imo dass alle anderen Werte außer dem aktiven ungültig sind.
Nach dem alten C++ Standard wäre jeder Zugriff auf einen anderen Wert als den zuletzt beschriebenen explizit undefiniertes Verhalten.
Die Passage wurde im neuen aber geändert und dort bin ich mir grad nicht ganz sicher, ob es nun undefiniertes Verhalten ist, oder ob einfach nur nirgendwo steht was genau rauskommen soll.
Aber ob schon rein der Versuch darauf zuzugreifen oder einfach nur das Ergebnis undefiniert ist, ändert jetzt nix dran, dass man sowas nicht tun sollte.
Falls der Standard da tatsächlich eine Grauzone hat, würd ich mich auf jeden Fall nicht drauf verlassen was da rauskommt, denn das wäre dann imo ganz klar ein Bug im Standard...
-
dot schrieb:
pyhax schrieb:
Can be stored. Aber da steht doch nichts von lesen, oder?
Das impliziert imo dass alle anderen Werte außer dem aktiven ungültig sind.
Nach dem alten C++ Standard wäre jeder Zugriff auf einen anderen Wert als den zuletzt beschriebenen explizit undefiniertes Verhalten.Wo liest du das heraus?
-
camper schrieb:
dot schrieb:
pyhax schrieb:
Can be stored. Aber da steht doch nichts von lesen, oder?
Das impliziert imo dass alle anderen Werte außer dem aktiven ungültig sind.
Nach dem alten C++ Standard wäre jeder Zugriff auf einen anderen Wert als den zuletzt beschriebenen explizit undefiniertes Verhalten.Wo liest du das heraus?
Ich hab den alten Standard nichtmehr hier und kann grad kein entsprechendes Draft finden. Ich hab einfach irgendwo im Hinterkopf dass der sowas in Richtung "jeder Zugriff auf einen anderen als den zuletzt beschriebenen Member ist UB" gesagt hat. Mag natürlich sein dass ich mich irre...