malloc对内存对齐有哪些保证?

时间:2011-12-20 12:58:59

标签: c memory-management malloc

我遇到了以下代码:

int main()
{
    char *A=(char *)malloc(20);
    char *B=(char *)malloc(10);
    char *C=(char *)malloc(10);
    printf("\n%d",A);
    printf("\t%d",B);
    printf("\t%d\n",C);
    return 0;
}  
//output--   152928264     152928288    152928304

我想知道malloc()如何完成分配和填充。查看输出我可以看到起始地址是8的倍数。还有其他规则吗?

4 个答案:

答案 0 :(得分:10)

根据this documentation page

  

在GNU系统中由malloc或realloc返回的块的地址始终是8的倍数(或64位系统上的16)。

通常,malloc实现是特定于系统的。所有这些都为自己的簿记(例如分配的块的实际长度)保留了一些内存,以便在您调用free时能够正确释放该内存。如果需要与特定边界对齐,请使用其他功能,例如posix_memalign

答案 1 :(得分:4)

唯一的标准规则是malloc返回的地址将适当地对齐以存储任何类型的变量。这究竟意味着什么是平台特定的(因为对齐要求因平台而异)。

答案 2 :(得分:0)

对于32位Linux系统:
当malloc()分配内存时,它以8的倍数(8的填充)分配内存,并为记账分配额外的8个字节。

例如:

  

malloc(10)和malloc(12)将分配24字节内存(填充后为16字节+8   用于簿记的字节。)

malloc()执行填充,因为返回的地址将是8的倍数,因此对任何类型的指针都有效。当我们调用自由函数时,使用簿记8个字节。簿记字节存储已分配内存的长度。

答案 3 :(得分:0)

C标准规定malloc()的结果必须可转换为任何合法指针类型。所以

... = (DataType *)malloc(...);

无论DataType是什么类型,都必须是可能的。

如果系统对某些数据类型有内存对齐要求,则malloc()必须考虑到这一点。而且由于malloc()无法知道将结果转换为哪种指针类型,因此它必须始终遵循最严格的内存对齐要求。

标准中的原始措辞为:

如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给具有基本对齐要求的任何类型的对象的指针,然后将其用于在分配的空间中访问此类对象或此类对象的数组(直到明确释放了空间)。

来源: ISO / IEC 9899:201x (又名 ISO C11

例如如果系统要求int对齐4字节,而long对齐8字节,则malloc()必须返回8字节对齐的内存,因为它不知道您是否要强制转换结果到intlong

从理论上讲,如果您请求的字节数少于sizeof(long),则强制转换为long *是无效的,因为long甚至都不适合该内存。有人可能认为在这种情况下,malloc()可以选择较小的对齐方式,但这不是标准所说的。标准中的对齐要求不取决于分配的大小!

由于许多CPU和许多操作系统确实有对齐要求,因此大多数malloc实现将始终返回对齐的内存,但是遵循的对齐规则是系统特定的。还有一些CPU和系统没有对齐要求,在这种情况下,malloc()可能还返回未对齐的内存。

如果您依赖特定的对齐方式,则可以使用 ISO C11 标准中定义的aligned_alloc(),从而可以将存在该C11编译器的所有系统移植到您的系统中,或者可以使用posix_memalign(),它在IEEE Std 1003.1-2001 (又名 POSIX 2001 )中定义,并且在所有符合POSIX的系统以及尽可能符合POSIX(例如Linux)。

有趣的事实:
尽管事实上macOS上没有数据类型的内存对齐要求超过8,但macOS上的malloc()始终返回16字节对齐的内存。原因是SSE。某些SSE指令要求16字节对齐,并且通过确保malloc()始终返回16字节对齐的内存,Apple通常可以在其标准库中使用SSE优化。