gpt4 book ai didi

linux - ARM 上未对齐内存访问的函数

转载 作者:太空狗 更新时间:2023-10-29 11:49:31 37 4
gpt4 key购买 nike

我正在从事一个从内存中读取数据的项目。其中一些数据是整数,在未对齐的地址访问它们时出现问题。我的想法是为此使用 memcpy,即

uint32_t readU32(const void* ptr)
{
uint32_t n;
memcpy(&n, ptr, sizeof(n));
return n;
}

我从项目源中找到的解决方案与这段代码相似:

uint32_t readU32(const uint32_t* ptr)
{
union {
uint32_t n;
char data[4];
} tmp;
const char* cp=(const char*)ptr;
tmp.data[0] = *cp++;
tmp.data[1] = *cp++;
tmp.data[2] = *cp++;
tmp.data[3] = *cp;
return tmp.n;
}

所以我的问题:

  1. 第二个版本不是未定义的行为吗? C 标准在 7 处的 6.2.3.2 指针中说:

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned 57) for the pointed-to type, the behavior is undefined.

由于调用代码在某些时候使用了 char* 来处理内存,因此必须进行一些从 char*uint32_t* 的转换。那么,如果 uint32_t* 没有正确对齐,这不是未定义行为的结果吗?如果它,那么该函数就没有意义,因为您可以编写 *(uint32_t*) 来获取内存。此外,我想我在某处读到编译器可能期望 int* 正确对齐,任何未对齐的 int* 也意味着未定义的行为,因此生成的代码此函数可能会创建一些快捷方式,因为它可能希望函数参数正确对齐。

  1. 原始代码在参数和所有变量上都有 volatile,因为内存内容可能会改变(它是驱动程序内部的数据缓冲区(无寄存器))。也许这就是它不使用 memcpy 的原因,因为它不适用于 volatile 数据。但是,这在哪个世界有意义?如果基础数据可以随时更改,那么所有的赌注都会落空。数据甚至可以在这些字节复制操作之间发生变化。所以你必须有某种互斥锁来同步对这些数据的访问。但是,如果您有这样的同步,为什么还需要 volatile?

  2. 是否有针对此内存访问问题的规范/公认/更好的解决方案?经过一番搜索,我得出的结论是,你需要一个互斥锁,不需要 volatile,可以使用 memcpy

附言:

# cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 10 (v7l)
BogoMIPS : 1581.05
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 10

最佳答案

这段代码

uint32_t readU32(const uint32_t* ptr)
{
union {
uint32_t n;
char data[4];
} tmp;
const char* cp=(const char*)ptr;
tmp.data[0] = *cp++;
tmp.data[1] = *cp++;
tmp.data[2] = *cp++;
tmp.data[3] = *cp;
return tmp.n;
}

将指针作为 uint32_t * 传递。如果它实际上不是 uint32_t,那就是 UB。该参数可能应该是 const void *

在转换本身中使用 const char * 不是未定义的行为。根据 6.3.2.3 指针the C Standard 的第 7 段(强调我的):

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

关于直接在特定硬件上访问内存/寄存器的正确方法,使用 volatile 没有规范/公认/最佳解决方案。任何解决方案都将特定于您的系统并且超出标准 C 的范围。

关于linux - ARM 上未对齐内存访问的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45506130/

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