Malloc和未对齐的内存

时间:2013-06-29 13:24:40

标签: c malloc

malloc()文档说返回的指针适合于任何类型的变量。在我的系统上,long double的大小为12,但malloc()返回的一些指针在8字节边界上对齐而不是12(ptr%12给出4)。谁能指出我在这里失踪了什么?提前谢谢。

5 个答案:

答案 0 :(得分:5)

显然,long double不需要与12个字节对​​齐。在像你这样的系统上,原始C类型的最大对齐是double的8个字节。不要混淆对齐和大小 - 虽然许多较小的(特别是原始的)类型必须自然对齐 - 也就是说,与它们自己的大小对齐 - 这对于较大的数据类型(想想碎片)是禁止的,并且不会使任何更容易硬件

答案 1 :(得分:4)

gcc for Linux和x86上有:

sizeof (long double) == 12

gcc上用于Linux,x64用于:

sizeof (long double) == 16

x64 long double的ABI对齐要求是16 - 字节。对于x86,任何类型都不需要超过8个字节的对齐。

要尊重glibc malloc返回与8对齐的内存对象 - 32-bit系统上的字节并在16上对齐 - 64的字节} -bit systems。

来自glibc doc:

  

malloc为您提供的块保证对齐,以便它可以保存任何类型的数据。在GNU系统上,地址在大多数系统上始终是8的倍数,在64位系统上是16的倍数。

答案 2 :(得分:3)

在任何理智的cpu体系结构中,对于大小为12的对象,最大可能的对齐要求是4.对齐要求必须是2的幂,才能均匀地划分类型的大小。实际上,这会给出非常差的对齐(跨越缓存行甚至页面的对象!),这就是x86_64 ABI将long double的大小更改为16的原因:这样就可以将它对齐而不是跨越任何边界。

答案 3 :(得分:0)

malloc将为任何类型返回正确对齐的内存,因为它返回的指针通常会转换为任意类型的指针,这种转换通常(读取:无限接近100%的时间)a无操作。对于任何体系结构和编译器,任何类型的最大对齐都是常量,通常它是所有基本类型的最大对齐。但是,对象的大小应该是其对齐的倍数。有时,必须通过向对象内的值添加填充来满足此要求。

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

答案 4 :(得分:0)

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

如果是long double,则转换为

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

使用gcc / x86和

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

使用gcc / x64,在这两种情况下long double都具有80位扩展精度。

如果我们不受约束的限制,我们最自然会最终得到

sizeof (long double) == 10

在存在对齐的情况下,我们要么必须使用2的对齐(我们不是出于效率原因),要么将填充引入数组,以便元素正确对齐。这违反了C语言的语义,数组的大小是其元素大小和计数的乘积。