gpt4 book ai didi

c - 奇怪的指针行为

转载 作者:行者123 更新时间:2023-11-30 15:33:20 24 4
gpt4 key购买 nike

我有一个缓冲区,其中包含先前从套接字读取的数据。根据缓冲区中存储的信息,我可以从规范中得知整个数据长度(91 字节),我知道我需要检索的其他信息的位置(32 位整数和 16 位整数,我们称它们为 uid 和 suid)。

unsigned char buffer[1024];
uint32_t uid;
uint16_t suid;

uid = ntohl ( *((uint32_t*) (buffer + sizeof (struct pktheader))) );

suid = ntohs ( *((uint16_t*) (buffer + sizeof (struct pktheader) + sizeof (uint32_t))) );

此代码是针对 ARM 进行交叉编译的,由于某些意外原因,uid 的内容填充了不正确的字节,这些字节是缓冲区的一部分,但位于(!)我要检索的内容之前。好像偏移量计算不正确。奇怪的是,suid 的含量足够了。

您能解释一下这种行为是如何可能的吗?我知道从我提供的信息来看这可能很困难...我们可以排除 sizeof (struct pktheader) 的错误值,我已经仔细检查过。缓冲区中的内容如规范中所定义。我什至找到了一个使用 memcpy 的工作解决方案,使用相同的偏移计算来获取每个部分,因此我们几乎可以排除混合数据的可能性。

我和我的同事讨论了这个问题,他的专业猜测是发生了一些自动对齐行为,指出偏移量仅差了 2 个字节。不过我想了解更多。

到目前为止,我非常喜欢这种结构,以便访问存储在缓冲区中的各个部分。

最佳答案

正如 @Dark Falcon 所建议的,这几乎肯定是一个对齐问题。最有可能的是,CPU 忽略了地址的底部两位并执行了加载对齐。

虽然不支持未对齐负载可能看起来是一个奇怪的设计选择,但它主要与门数和功耗有关。否则,CPU 需要应对两种令人讨厌的情况:

  • 加载/存储跨越缓存行边界
  • 加载/存储跨越页面边界

这两者都需要大量的门来修复 - 特别是后者 - 因为内存访问实际上跨越了缓存行页边界。在大多数 ARM 部件中,栅极、芯片空间和功耗都非常宝贵。

此行为也完全兼容 C 和 C++ 标准,因此上面的代码不是普遍可移植的。

在具有未对齐访问的缓冲区上覆盖 structunion 也不安全 - 编译器将放置它以避免未对齐访问,并且也不会初始化任何留下间隙(所以永远不要使用 memcmp 来比较它们)。这也正是您不想要的有线格式数据包。

使用结构打包更安全 - 编译器将知道哪些内存访问是允许的,哪些是不允许的,并且会生成较小的读取和写入,以免执行未对齐的访问。然而,直到最近,启用打包的机制一直是编译器特定的 - 因此也不可移植。

唯一真正可移植的实现选择是按字节访问(并转换以合并数据)。

关于c - 奇怪的指针行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23765901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com