我试图理解与posix_memalign
相关的内存开销 - 换句话说,如果posix_memalign
依赖于边界标记以及这种标记有多大。
所以我编写了以下(非常简单的)程序(linux x86_64平台,“gcc -m64”):
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char* argv[])
{
int i;
void* prev;
void* memp;
int align = atoi(argv[1]);
int alloc = atoi(argv[2]);
for (i = 0; i < 5; ++i)
{
if (posix_memalign(&memp, align, alloc))
{
fprintf(stderr, "allocation failed\n");
return 1;
}
if (i == 0)
printf("allocated %d bytes at 0x%08x\n", alloc, memp);
else
printf("allocated %d bytes at 0x%08x (offset: %d)\n",
alloc, memp, (int)(memp-prev));
prev = memp;
}
return 0;
}
然而,结果让我感到困惑......
$ /tmp/test 8 1
allocated 1 bytes at 0x0133a010
allocated 1 bytes at 0x0133a030 (offset: 32)
allocated 1 bytes at 0x0133a050 (offset: 32)
allocated 1 bytes at 0x0133a070 (offset: 32)
allocated 1 bytes at 0x0133a090 (offset: 32)
same for allocations of 2 to 24 bytes, until:
$ /tmp/test 8 25
allocated 25 bytes at 0x0198c010
allocated 25 bytes at 0x0198c040 (offset: 48)
allocated 25 bytes at 0x0198c070 (offset: 48)
allocated 25 bytes at 0x0198c0a0 (offset: 48)
allocated 25 bytes at 0x0198c0d0 (offset: 48)
same for allocations of 26 to 40 bytes, until:
$ /tmp/test 8 41
allocated 41 bytes at 0x0130c010
allocated 41 bytes at 0x0130c050 (offset: 64)
allocated 41 bytes at 0x0130c090 (offset: 64)
allocated 41 bytes at 0x0130c0d0 (offset: 64)
allocated 41 bytes at 0x0130c110 (offset: 64)
所以我最初得出结论,最小分配是32字节,而posix_memalign
使用了8字节边界标记。
使用16字节对齐获得了相同的结果。但是32字节对齐的事情很奇怪:
$ /tmp/test 32 1
allocated 1 bytes at 0x0064c040
allocated 1 bytes at 0x0064c080 (offset: 64)
allocated 1 bytes at 0x0064c120 (offset: 160)
allocated 1 bytes at 0x0064c160 (offset: 64)
allocated 1 bytes at 0x0064c200 (offset: 160)
same for allocations of 2 to 24 bytes, until:
$ /tmp/test 32 25
allocated 25 bytes at 0x01e0c040
allocated 25 bytes at 0x01e0c0c0 (offset: 128)
allocated 25 bytes at 0x01e0c140 (offset: 128)
allocated 25 bytes at 0x01e0c1c0 (offset: 128)
allocated 25 bytes at 0x01e0c240 (offset: 128)
same for allocations of 26 to 40 bytes, until:
$ /tmp/test 32 41
allocated 41 bytes at 0x00a72040
allocated 41 bytes at 0x00a720a0 (offset: 96)
allocated 41 bytes at 0x00a72160 (offset: 192)
allocated 41 bytes at 0x00a721c0 (offset: 96)
allocated 41 bytes at 0x00a72280 (offset: 192)
有人可以解释这种行为吗?我完全失去了......
答案 0 :(得分:0)
posix_memalign仅保证最小对齐。因此,如果您巧合地获得0x00a72000
之类的内容,可能会与0x1000
字节对齐,但这并不意味着浪费了大量内存来填充它。即使您的第一个示例几乎也显示了这一点 - 它始于0x0198c010
并在每个示例之后递增0x30
。最终会击中一个清除了许多低位的地址。
请记住,glibc中的malloc不是&#34;愚蠢的&#34;一个只是直接分页/块。如果您想了解有关其内部行为的更多信息,您应该阅读它所基于的分配器。 glibc使用基于ptmalloc的dlmalloc。我不认为glibc manual本身就其内部设计决策深入探讨。