我有以下结构:
struct foo
{
int a;
char b;
};
它存储在内存中,指向它的指针可以是未对齐的(奇数地址)。
那么,这样安全吗?:
const struct foo a = *((struct foo*)char_ptr);
我很担心,因为源结构的整数成员可以在奇数地址中。在某些系统中,从奇数地址读取(多字节)整数会导致问题。
修改
为了避免关于const
的使用的偏离主题评论,我确实从代码中删除了const
。 (我从不将const指针强制转换为非const指针,即使在这种情况下也不应该导致任何问题)
更多关于问题的背景:
这种结构是协议框架的一部分。它可以在框架内的任何偏移处。在实际代码中,struct具有__attribute__((packed))
属性。但这可能不会改变答案?
无论如何,我可以使用memcopy
和非const a
来解决问题。但是我想使用这种分配,因为它似乎更优雅(如果它是安全的)。
答案 0 :(得分:2)
见Data structure padding。在大多数系统中,结构将是对齐的。内部成员地址将按照各自的大小进行对齐,同时进行malloc'ing自身。
如果手动创建内存池&使用其中的一些部分来存储你的struct对象,然后编译器不会保证你对齐,但是如果你使用malloc来创建struct对象,通常编译器很头疼,为了给你对齐的地址,如果需要在struct元素之间填充。
答案 1 :(得分:1)
如果从数据指针不一定对齐的源获取数据,那么你可以做的唯一安全的事就是memcpy并希望你的编译器不是“聪明的”并假装未对齐的指针是实际对齐,memcpy可以优化(有几个旧版本的gcc有这个bug,要求你编写一个不称为memcpy的自定义memcpy函数)。根据您的体系结构,您可以通过不正确的对齐访问来逃避,但它几乎肯定会更慢,有时甚至可以通过内核陷阱进行模拟。
副轶事:这通常是操作系统中网络堆栈中的问题,其中以太网报头的奇数大小使得IP报头未对齐,并且硬件无法使接收到的数据包不对齐(某些DMA引擎)只能在4字节边界上写入数据),这需要在软件中再次复制整个标题(或整个数据包)。
答案 2 :(得分:1)
不,它不安全,除非您知道指针具有结构所需的对齐。
以下是一些了解指针是否具有必要对齐的方法:
malloc
)的结果,它保证返回的地址适合分配给任何用途(malloc
确实保证)。uintptr_t
并测试其对齐方式,前提是C实现支持此功能。如果您不知道指针具有必要的对齐方式,则不应通过转换后的指针访问该结构。相反,您可以定义一个新结构并使用memcpy
从指针到char复制到新结构中。