c++ - 在 memcpy 缓冲区 UB 上使用 reinterpret_cast 吗?

标签 c++ language-lawyer

鉴于代码

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/

相关文章:

c++ - 序列点和评估顺序(预增量)

c++ - 显式模板特化的语法

c++ - 为什么当赋值运算符的左操作数时,数组名称不会衰减为指针?

c++ - Visual Studio 2008调试;在写入值时中断

c# - 适用于 C/C++/C# 的免费静态代码扫描器

c++ - Variadic 函数不会用 clang 编译

c++ - BK4504警告如何处理

c++ - 为什么 Visual Studio C++ 编译器拒绝将枚举作为模板参数?

c++ - std::array 的大小是否由标准定义

c++ - 当前草案是否允许形成由两个非静态成员声明组成的重载集,其中一个具有引用限定符