使用指针分配struct值是否安全

时间:2012-12-05 12:14:36

标签: c

我有以下结构:

struct foo
{
   int  a;
   char b;
};

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

那么,这样安全吗?:

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

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

修改  为了避免关于const的使用的偏离主题评论,我确实从代码中删除了const。 (我从不将const指针强制转换为非const指针,即使在这种情况下也不应该导致任何问题)

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

无论如何,我可以使用memcopy和非const a来解决问题。但是我想使用这种分配,因为它似乎更优雅(如果它是安全的)。

3 个答案:

答案 0 :(得分:2)

Data structure padding。在大多数系统中,结构将是对齐的。内部成员地址将按照各自的大小进行对齐,同时进行malloc'ing自身。

如果手动创建内存池&使用其中的一些部分来存储你的struct对象,然后编译器不会保证你对齐,但是如果你使用malloc来创建struct对象,通常编译器很头疼,为了给你对齐的地址,如果需要在struct元素之间填充。

答案 1 :(得分:1)

如果从数据指针不一定对齐的源获取数据,那么你可以做的唯一安全的事就是memcpy并希望你的编译器不是“聪明的”并假装未对齐的指针是实际对齐,memcpy可以优化(有几个旧版本的gcc有这个bug,要求你编写一个不称为memcpy的自定义memcpy函数)。根据您的体系结构,您可以通过不正确的对齐访问来逃避,但它几乎肯定会更慢,有时甚至可以通过内核陷阱进行模拟。

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

答案 2 :(得分:1)

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

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

  • 在将指针转换为指向char的指针之前,指针最初是指向此结构类型的指针。
  • 指针是内存分配例程(例如malloc)的结果,它保证返回的地址适合分配给任何用途(malloc确实保证)。
  • 指针是从保存所需对齐的方式计算出来的。
  • 您将指针转换为uintptr_t并测试其对齐方式,前提是C实现支持此功能。
  • 您的C实现(特别是操作系统和处理器)允许对结构中类型的对象进行未对齐访问。

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