鉴于代码
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;
是
reinterpret_cast
的用法在这种情况下,UB?我会说是的,因为 memcpy
不开始实例的生命周期,因此违反了严格的别名规则(这就是 std::bit_cast
已添加到 C++20 的原因)。如果我用另一个
memcpy
替换类型转换(读取指针)程序会被很好地定义吗?
最佳答案
是的,此代码具有未定义的行为。没有 A*
类型的对象在 buffer.data()
指向的位置.您所做的只是将此类指针的对象表示复制到您的 vector 中 [basic.types]/4 .由于指针可以简单地复制 [basic.types]/9 , 如果您要将这些字节复制回 A*
类型的实际对象中然后 delete
那个值,这将是明确定义的 [basic.types]/3 .所以这
A* ptr;
std::memcpy(&ptr, buffer.data(), sizeof(ptr));
delete ptr;
会好的。
请注意,在原始示例中调用未定义行为的不是强制转换本身,而是您随后尝试读取类型
A*
的对象的值。通过强制转换点获得的指针不存在。所有存在的指针指向的是一个类型为 unsigned char
的对象序列。 .型号A*
不是可用于访问类型 unsigned char
的对象的存储值的类型[basic.lval]/8 …
关于c++ - 在 memcpy 缓冲区 UB 上使用 reinterpret_cast 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59716273/