2013-06-29 64 views
4

malloc()文档说,返回的指针适合任何类型的变量。在我的系统中,long double的大小为12,但malloc()返回的一些指针在8字节边界上对齐,而不是12(ptr%12给出4)。任何人都可以指出我在这里错过了什么?提前致谢。Malloc和未对齐的内存

+0

你从哪里阅读了关于malloc返回对齐的内存? –

+3

在手册页中。请参阅此处的返回值http://linux.die.net/man/3/malloc。还是我误解了一些东西? – user44990

+7

12字节长的双打不需要12字节对齐。 –

回答

5

很明显,long double不需要对齐到12个字节。在您的系统上,原始C类型的最大对齐为double的8个字节。不要混淆对齐和大小 - 而许多较小的(尤其是原始的)类型必须自然对齐 - 即按照自己的大小对齐 - 这对于较大的数据类型来说是禁止的(思考碎片),并且不会使硬件。

+0

哪些较大的类型? – Sebivor

+0

@undefinedbehaviour:'struct's。 –

+0

@MatteoItalia ...但结构的第一个成员必须适合对齐或发生未定义的行为。这是没有意义的。你知道可以打开英特尔机器上的总线错误检查吗?也许你应该在断言之前验证这一点...... – Sebivor

3

gcc Linux和x86您有:

sizeof (long double) == 12

gcc Linux和x64您有:

sizeof (long double) == 16

的ABI对齐的要求x64long double16-bytes。对于x86,没有类型需要超过8字节的对齐方式。

尊重该glibcmalloc返回存储器的对象与8 -bytes上32-bit系统对准并上16 -bytes为64位系统对准。

glibc DOC:

确定malloc给你保证对齐,以便它可以保存任何类型的数据块。在GNU系统上,大多数系统的地址总是8的倍数,64位系统的地址总是16的倍数。

0

malloc将返回存储器的任何类型的适当对准,因为通常它返回指针被转换为任意类型的指针和这样的转换是典型地(读:无限接近的时间的100%)无-OP。对于任何体系结构和编译器来说,任何类型的最大对齐是一个常量,通常它是所有基本类型对齐的最大值。对象的大小应该是其对齐的倍数。有时这种要求必须通过向对象内的值添加填充来满足。

如果您的编译器足够现代化,它将支持_Alignof,类似于sizeof,因此您可以使用小程序检查实际对齐方式。我认为在你的架构上最大对齐是4.如果malloc总是返回由8对齐的地址,那么它仍然符合。对于malloc来说,并不少见的是一个对齐类型的最大对齐的倍数。

0

你错过了一个类型的大小必须是其对齐的倍数(它受到实际硬件的限制),它们不必相同。

long double情况下,这转化为

_Alignof (long double) == 4 
sizeof (long double) == 12 

用gcc/x86和

_Alignof (long double) == 16 
sizeof (long double) == 16 

用gcc/64,其中,在这两种情况下long double具有80位的扩展精度。

如果我们没有受到限制对齐,最自然的,我们会最终

sizeof (long double) == 10 

在对齐的情况下,我们会要么不得不去为2的比对(我们不要”出于效率原因),或者向数组引入填充,以便元素正确对齐。这违反了C语言的语义,数组的大小是其元素大小和数量的乘积。

3

在任何理智的cpu架构上,对于大小为12的对象,最大可能的对齐要求是4.对齐要求必须是2的幂,该大小等于该类型的大小。事实上,这给出了非常差的对齐方式(跨越缓存行甚至页面的对象!),这就是为什么x86_64 ABI将long double的大小更改为16:这样就有可能使它不会跨越任何边界。