我正在研究内存池实现,我对指针对齐有点困惑......
假设我有一个分配固定大小内存块的内存池,在创建内存池时我 malloc((size)*(num of blocks))。如果分配的是对象并且大小来自 sizeof 运算符对齐不应该是一个问题,但是如果大小不均匀(他/她出于任何原因想要 100 字节块),那么当我拆分 malloc 给出的块时我最终会得到未对齐的指针。我的问题是我应该总是将块对齐到某个边界,如果是的话,是哪个?
在大多数 x86 实现中,正确的对齐至少是有帮助的(在性能方面)(在其他架构中,某种对齐实际上是强制性的)。您可能会要求(像 calloc 那样)一对参数,以字节为单位的项目大小和项目数,而不仅仅是一个(以字节为单位的大小,像 malloc 那样);然后你可以本质上对齐(通过四舍五入块大小)到项目大小之上的 2 的下一个更高的幂(但切换到 16 以上的 16 个字节的倍数,不要永远加倍,就像@derobert 推荐和解释的那样! -)。这样,如果调用者只想要 N 个字节而不需要任何对齐或填充,他们总是可以请求 N 个每个 1 字节的项目(就像他们使用 calloc 并且出于相同的原因;-)。
X86 无需对齐即可工作,但数据对齐时性能更好。type的对齐方式通常是 sizeof( type ),最多为 16(字节)。
我写了这个愚蠢的测试程序只是为了确定(假设 malloc 知道它在做什么),它在我的 amd64 盒子上返回 16。在 32 位模式下编译时返回 8:
#include <stdlib.h>
#include <stdio.h>
int main() {
int i;
unsigned long used_bits = 0, alignment;
for (i = 0; i < 1000; ++i) {
used_bits |= (unsigned long)malloc(1); /* common sizes */
used_bits |= (unsigned long)malloc(2);
used_bits |= (unsigned long)malloc(4);
used_bits |= (unsigned long)malloc(8);
used_bits |= (unsigned long)malloc(16);
used_bits |= (unsigned long)malloc(437); /* random number */
}
alignment = 1;
while (!(used_bits & alignment)) {
alignment <<= 1;
}
printf("Alignment is: %lu\n", alignment);
return 0;
}