2

我有以下结构:

struct foo
{
   int  a;
   char b;
};

它存储在内存中,指向它的指针可以是未对齐的(奇数地址)。

那么,这安全吗?:

const struct foo a = *((struct foo*)char_ptr); 

我很担心,因为源结构的整数成员可能位于奇数地址。在某些系统中,从奇数地址读取(多字节)整数会导致问题。

编辑: 为了避免关于使用的偏离主题的评论const,我确实const从代码中删除了 a 。(我从不将 const 指针转换为非 const 指针,即使在这种情况下它不应该引起任何问题)

更多关于问题的上下文:这种结构是协议框架的一部分。它可以在框架内的任何偏移处。在实际代码中,结构具有__attribute__((packed))属性。但这可能不会改变答案?

无论如何,我可以使用memcopy和非常量a来解决问题。但我想使用 assingment,因为它似乎是更优雅的方式(如果它是安全的)。

4

3 回答 3

2

请参阅数据结构填充。在大多数系统上,结构将对齐,内部成员地址将根据它们各自的大小对齐,同时 malloc'ing 本身。

如果您手动创建一个内存池并使用其中的某个部分来存储您的 struct 对象,那么编译器将无法保证您对齐,但是如果您使用 malloc 创建 struct 对象,编译器通常会很头疼,给您对齐的地址,如果需要,在结构元素之间使用填充。

于 2012-12-05T12:22:44.627 回答
1

如果您从指向数据的指针不一定对齐的源获取数据,那么您可以做的唯一安全的事情是 memcpy 并希望您的编译器不是“智能”并假装未对齐的指针实际上是对齐的并且memcpy 可以优化(有几个旧版本的 gcc 有这个错误,需要你编写一个不称为 memcpy 的自定义 memcpy 函数)。根据您的架构,您可以摆脱不正确对齐的访问,但几乎可以肯定它会更慢,有时甚至会通过内核陷阱进行模拟。

附带轶事:这通常是操作系统中的网络堆栈中的一个问题,其中以太网标头的奇数大小使 IP 标头未对齐,并且如果硬件没有能力错位接收的数据包(某些 DMA 引擎只能写入4 字节边界上的数据),这需要在软件中再次复制整个标头(或整个数据包)。

于 2012-12-05T12:35:17.227 回答
1

不,这不安全,除非您知道指针具有结构所需的对齐方式。

以下是了解指针是否具有必要对齐的一些方法:

  • 该指针最初是指向此结构类型的指针,然后才转换为指向 char 的指针。
  • 指针是内存分配例程(例如malloc)的结果,该例程保证返回的地址被适当地分配给任何用途(malloc确实保证)。
  • 指针是根据上述之一以保持所需对齐的方式计算的。
  • 您将指针转换为 auintptr_t并测试其对齐方式,前提是您的 C 实现支持这一点。
  • 您的 C 实现(尤其是操作系统和处理器)允许对结构中类型的对象进行非对齐访问。

如果您不知道指针具有必要的对齐方式,则不应通过转换后的指针访问该结构。相反,您可以定义一个新结构并使用memcpy它从指向字符的指针复制到新结构中。

于 2012-12-05T14:30:00.980 回答