如果您的实现具有需要 16 字节对齐的标准数据类型(long long
例如),malloc
则已经保证您返回的块将正确对齐。C99 的第 7.20.3 节规定The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object.
您必须将完全相同的地址传回free
给您malloc
。没有例外。所以是的,你需要保留原件。
如果您已经有一个需要 16 字节对齐的类型,请参见上面的 (1)。
除此之外,您可能会发现您的malloc
实现无论如何都会为您提供 16 字节对齐的地址以提高效率,尽管标准不能保证这一点。如果需要,您可以随时实现自己的分配器。
我自己,我会在其malloc16
上实现一个层malloc
,将使用以下结构:
some padding for alignment (0-15 bytes)
size of padding (1 byte)
16-byte-aligned area
然后让你的malloc16()
函数调用malloc
获得比请求大 16 字节的块,找出对齐区域应该在哪里,将填充长度放在其前面并返回对齐区域的地址。
对于free16
,您只需查看给定地址之前的字节以获得填充长度,从中计算出 malloc 块的实际地址,然后将其传递给free
.
这是未经测试的,但应该是一个好的开始:
void *malloc16 (size_t s) {
unsigned char *p;
unsigned char *porig = malloc (s + 0x10); // allocate extra
if (porig == NULL) return NULL; // catch out of memory
p = (porig + 16) & (~0xf); // insert padding
*(p-1) = p - porig; // store padding size
return p;
}
void free16(void *p) {
unsigned char *porig = p; // work out original
porig = porig - *(porig-1); // by subtracting padding
free (porig); // then free that
}
中的魔法线malloc16
将p = (porig + 16) & (~0xf);
16 添加到地址,然后将低 4 位设置为 0,实际上将其带回到下一个最低对齐点(+16
保证它超过了 macoc'ed 块的实际开始)。
现在,我并没有声称上面的代码是杂乱无章的。您必须在感兴趣的平台上对其进行测试,看看它是否可行。它的主要优点是它抽象了丑陋的部分,因此您永远不必担心它。