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

Amo*_*rma 11 c malloc memory-management

我遇到了以下代码:

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
Run Code Online (Sandbox Code Playgroud)

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

das*_*ght 14

根据此文档页面,

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

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


Mec*_*cki 9

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

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

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

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

标准中的原始措辞是:

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

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

例如,如果系统需要int4 字节对齐和long8 字节对齐,malloc()则必须返回 8 字节对齐的内存,因为它无法知道您是否要将结果转换为 toint *或 to long *

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

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

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

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


NPE*_*NPE 5

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