Angesichts des Codes
struct A {};
auto obj = new A;
std::vector<unsigned char> buffer;
buffer.resize(sizeof(obj));
std::memcpy(buffer.data(), &obj, sizeof(obj)); // this copies the pointer, not the object!
// ...
auto ptr = *reinterpret_cast<A**>(buffer.data()); // is this UB?
delete ptr;
ist die Verwendung von reinterpret_cast
in diesem Fall UB? Ich würde ja sagen, da memcpy
die Lebensdauer einer Instanz nicht beginnt und somit gegen die strenge Aliasing-Regel verstößt (weshalb std::bit_cast
C ++ 20 hinzugefügt wurde).
Und wenn ich die Besetzung durch eine andere ersetze memcpy
(um den Zeiger zu lesen), wäre das Programm gut definiert?
c++
language-lawyer
Timo
quelle
quelle
buffer.data()
, der angeblich einen Zeiger auf enthältA
, nichtbuffer.data()
selbst, der ein Zeiger auf istA
.std::vector
? (IchA*
Objekt im Puffer befindet. Der Standard sagt über die Standardfunktion allocator :: allocate aus: "Rückgabe: Ein Zeiger auf das Anfangselement eines Arrays von Speichergrößenn * sizeof(T)
, das für Objekte vom Typ T entsprechend ausgerichtet ist ".Antworten:
Ja, dieser Code hat ein undefiniertes Verhalten.
A*
An der Stelle, auf die von gezeigt wird, befindet sich kein Objekt vom Typbuffer.data()
. Sie haben lediglich die Objektdarstellung eines solchen Zeigers in Ihren Vektor [basic.types] / 4 kopiert . Da Zeiger trivial kopierbar sind [basic.types] / 9 , wenn Sie diese Bytes in ein tatsächliches Objekt vom TypA*
und danndelete
den Wert davon zurückkopieren würden, wäre dies gut definiert [basic.types] / 3 . Also daswäre in Ordnung.
Beachten Sie, dass nicht die Umwandlung selbst in Ihrem ursprünglichen Beispiel undefiniertes Verhalten hervorruft, sondern Ihr nachfolgender Versuch, den Wert eines Objekts vom Typ zu lesen, das
A*
nicht vorhanden ist, wenn der Zeiger über die Umwandlungspunkte erhalten wurde. Alles, was dort ist, wo der Zeiger zeigt, ist eine Folge von Objekten vom Typunsigned char
. Der TypA*
ist kein Typ, mit dem Sie auf den gespeicherten Wert eines Objekts vom Typunsigned char
[basic.lval] / 8 … zugreifen können.quelle
A* a_ptr; std::memcpy(&a_ptr, buffer.data(), sizeof(a_ptr));
um den Zeiger wieder aus dem Puffer zu extrahieren. Anstatt derreinterpret_cast
in Timos Frage.unsigned char
, vielleicht mehr als eines.