Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the usage of reinterpret_cast on a memcpy buffer UB?

Given the code

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;

is the usage of reinterpret_cast in this case UB? I would say yes, because memcpy doesn't start the lifetime of an instance hence violating the strict aliasing rule (which is why std::bit_cast has been added to C++20).

And if I replace the cast with another memcpy (to read the pointer) would the program be well defined?

like image 604
Timo Avatar asked Jan 13 '20 12:01

Timo


1 Answers

Yes, this code has undefined behavior. There is no object of type A* at the location pointed to by buffer.data(). All you did was copy the object representation of such a pointer into your vector [basic.types]/4. Since pointers are trivially copyable [basic.types]/9, if you were to copy back these bytes into an actual object of type A* and then delete the value of that, that would be well-defined [basic.types]/3. So this

A* ptr;
std::memcpy(&ptr, buffer.data(), sizeof(ptr));
delete ptr;

would be fine.

Note that it is not the cast itself that invokes undefined behavior in your original example but your subsequent attempt to read the value of an object of type A* which does not exist where the pointer obtained via the cast points. All there exists where the pointer points is a sequence of objects of type unsigned char. The type A* is not a type that you may use to access the stored value of an object of type unsigned char [basic.lval]/8…

like image 190
Michael Kenzel Avatar answered Dec 12 '22 12:12

Michael Kenzel