我也想知道glibc malloc()是否这样做。
答案 0 :(得分:58)
假设你有结构。
struct S {
short a;
int b;
char c, d;
};
如果没有对齐,它将在内存中布局(假设采用32位架构):
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
问题在于,在某些CPU架构中,从内存加载4字节整数的指令仅适用于字边界。因此,您的程序必须使用单独的指令获取b
的每一半。
但如果记忆的布局如下:
0 1 2 3 4 5 6 7 8 9 A B
|a|a| | |b|b|b|b|c|d| | |
| | | |
然后访问b
变得简单明了。 (缺点是需要更多内存,因为填充字节。)
不同的数据类型具有不同的对齐要求。 char
通常为1字节对齐,short
为2字节对齐,4字节类型(int
,float
和指针位于32-位系统)要4字节对齐。
malloc
返回一个针对任何数据类型正确对齐的指针。
glibc malloc
返回16字节对齐的指针。
答案 1 :(得分:6)
Alignment要求指定可以将哪些地址偏移分配给哪些类型。这完全取决于实现,但通常基于字大小。例如,某些32位体系结构要求所有int
变量以四的倍数开始。在某些体系结构上,对齐要求是绝对的。在其他人(例如x86)上藐视它们只会带来性能损失。
malloc
需要返回适合任何对齐要求的地址。换句话说,返回的地址可以分配给任何类型的指针。从C99§7.20.3(内存管理功能):
如果分配则返回指针 成功适当地对齐以便 它可以被分配给指向任何的指针 对象的类型然后用于访问 这样的对象或这样的数组 分配的空间中的对象(直到 空间明确解除分配。)
答案 2 :(得分:1)
如果您有特定的内存对象需求(对于特定的硬件或库),您可以检查非便携式内存分配器,例如_aligned_malloc()
和memalign()
。这些可以很容易地在“便携式”界面后面抽象,但不幸的是非标准。
答案 3 :(得分:1)
malloc()
文档说:
[...] the allocated memory that is suitably aligned for any kind of variable.
对于您在C / C ++中所做的大多数事情都是如此。但是,正如其他人所指出的那样,存在许多特殊情况并需要特定的对齐。例如,英特尔处理器支持256位类型:__m256
,malloc()
肯定不会考虑这种类型。
同样,如果要为要分页的数据分配内存缓冲区(类似于mmap()
返回的地址等),那么你需要一个可能非常大的对齐,这会浪费大量的内存如果malloc()
返回的缓冲区始终与这些边界对齐。
在Linux或其他Unix系统下,我建议你使用posix_memalign()
函数:
int posix_memalign(void **memptr, size_t alignment, size_t size);
这是人们想要用于满足此类需求的最新功能。