23

我也想知道 glibc malloc() 是否这样做。

4

4 回答 4

77

假设你有这个结构。

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变得简单。(缺点是需要更多内存,因为填充字节。)

不同的数据类型有不同的对齐要求。char1 字节对齐、short2 字节对齐和 4 字节类型(32 位系统上的 、 和指针)4 字节对齐int是很常见的。float

mallocC 标准要求返回针对任何数据类型正确对齐的指针。

x86-64 上的glibcmalloc返回 16 字节对齐的指针。

于 2010-10-22T05:45:09.473 回答
10

对齐要求指定哪些地址偏移可以分配给哪些类型。这完全取决于实现,但通常基于字长。例如,一些 32 位架构要求所有int变量都以 4 的倍数开始。在某些架构上,对齐要求是绝对的。在其他(例如 x86)上,轻视它们只会带来性能损失。

malloc需要返回适合任何对齐要求的地址。换句话说,返回的地址可以分配给任何类型的指针。来自 C99 §7.20.3(内存管理功能):

如果分配成功,则返回的指针经过适当对齐,以便可以将其分配给指向任何类型对象的指针,然后用于访问已分配空间中的此类对象或此类对象的数组(直到空间被显式释放) .

于 2010-10-22T05:08:19.640 回答
1

如果您有特定的内存对齐需求(对于特定的硬件或库),您可以查看不可移植的内存分配器,例如_aligned_malloc()memalign()。这些可以很容易地在“便携式”接口后面抽象出来,但不幸的是它们是非标准的。

于 2010-10-22T05:17:25.810 回答
0

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);

这是人们想要用于此类需求的最新功能。

于 2012-12-26T09:23:28.267 回答