我找到了这段代码:
void* aligned_malloc(size_t required_bytes, size_t alignment) {
int offset = alignment - 1;
void* P = (void * ) malloc(required_bytes + offset);
void* q = (void * ) (((size_t)(p) + offset) & ~(alignment - 1));
return q;
}
这是C ++中对齐的malloc的实现。对齐的malloc是一个支持分配内存的函数,这样 返回的内存地址可被2的特定乘方整除。 示例:
align_malloc(1000,128)将返回一个内存地址,该地址是128的倍数,并且指向大小为1000字节的内存。
但是我不明白第4行。为什么将偏移量加倍?
谢谢
答案 0 :(得分:1)
为什么总和为偏移量的两倍?
offset
未被精确地相加两次。偏移量的首次使用是为了分配大小:
void* p = (void * ) malloc(required_bytes + offset);
第二次是对齐:
void* q = (void * ) (((size_t)(p) + offset) & ~(alignment - 1));
说明:
~(alignment - 1)
是offset
的求反(请记住int offset = alignment - 1;
),它为您提供遮罩,您需要满足所要求的对齐方式。以算术方式,将偏移量相加并对其取反按位和(&
),将为您提供对齐指针的地址。
该算术如何工作?首先,请记住,malloc()
的内部调用是required_bytes + offset
个字节。在这种情况下,不是您要求的对齐方式。例如,您想分配10个字节,对齐方式为16(因此所需的行为是分配一个10字节,该地址从一个可被16整除的地址开始)。因此,上面的malloc()
将为您提供10+16-1
= 25个字节。就可以被16整除而言,不一定从正确的地址开始。但是,此16-1
为0x000F
,其否定(~
)为0xFFF0
。现在我们按如下方式应用 bitwise和:p + 15 & 0xFFF0
,这将导致每个指针p
都是16的倍数。
但是,等等,为什么要首先添加alignment - 1
的偏移量呢?之所以这样做,是因为一旦获得p
返回的指针malloc()
, 您无法做的一件事(为了找到最接近的地址,该地址是所请求的对齐方式的倍数),请在之前 p
查找,因为这可能会跨入p
之前分配的地址空间。为此,首先要添加 alignment - 1
,考虑到这一点,它恰好是必须前进的最大值以实现对齐。
*感谢用户DevSolar的一些附加措辞。
注意1:要使这种方式起作用,对齐方式必须是2的幂。此代码段不会强制执行此类操作,因此可能导致意外行为。
注2:一个有趣的问题是如何使用此函数的返回值来实现这种分配的free()
版本。