c++ - 这是通过指针从 uint8_t vector 加载对象的安全方法吗?

标签 c++ pointers

我有一个 std::vector<uint8_t> buffer ;我想加载一个大于 uint8_t 的数据类型(在这个例子中 uint16_t target ,但可以是任何东西)。我知道这个对象的内容已经被复制到位置size_t IDbuffer .
据我所知,可以复制 target和:

uint16_t target = *((uint16_t*) &buffer[ID]);
它适用于 gcc version 9.3.0在使用 C++17 的 Ubuntu 上。
但它看起来肯定是无意的。那么这个使用安全吗?也就是说,只要我确定知道 ID+sizeof(target)在缓冲区内,我可以确定这将在所有操作系统上编译和运行而不会崩溃吗?

最佳答案

不,不是。你不能“假装”一个 uint16_t在它不存在的地方存在。
在某些情况下,这种类型的双关语是安全的。例如,您可以将所需类型的现有对象重新解释为字节序列(通过 char*unsigned char*std::byte* ),但反之则不然。 ( ref )
C++ 对“存在”什么对象非常挑剔,在使用对象之前,您必须遵循语言规则使对象正确存在。这不仅仅是字节。编译器的“优化”甚至可以在我们解决实际计算机上的对齐等低级问题之前破坏程序的预期行为。
为了确保安全,您需要将字节复制到新的 uint16_t 中。 :

uint16_t target = 0;
std::copy(
   reinterpret_cast<const char*>(&buffer[ID]),
   reinterpret_cast<const char*>(&buffer[ID]) + sizeof(uint16_t),
   reinterpret_cast<char*>(&target)
);
……或更短的:
uint16_t target = 0;
std::memcpy(&target, &buffer[ID], sizeof(uint16_t));
请注意,这里我们正在利用我上面描述的别名豁免来重新解释 uint16_t作为字节序列,写入该序列。
因此,这些版本是安全的,只要您复制的字节确实形成了 uint16_t 的有效表示。在您的系统上(这对于主流平台很容易保证)。

关于c++ - 这是通过指针从 uint8_t vector 加载对象的安全方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65508613/

相关文章:

c++ - 在 C++ 中重载 = 运算符的具体案例

c - 使用指针算术的字符串字谜

c - Pointer Dequeue——指针训练

c - 关于 C 语言中指针的相同输出

c++ - 构造函数中神秘的堆栈溢出

javascript - Google 的 V8 引擎真的限制每个进程 1 个 VM 吗?

c++ - 重启RPC服务

c++ - 如何通过捕获在函数中传递 lambda?

我可以/我应该释放 strtok 返回的指针吗

c - 指针指向指针的正确用法