我发现了这段代码:
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;
}
字符串
Aligned malloc是一个函数,它支持分配内存,使得返回的内存地址可以被2的特定幂整除。例如:
align_malloc(1000,128)将返回一个内存地址,该地址是128的倍数,并且指向大小为1000字节的内存。
但我不明白第四行为什么要把偏移量加两倍?
谢谢
1条答案
按热度按时间yrdbyhpb1#
为什么要把偏移量加两倍?
**
offset
并不是两次求和。**第一次使用offset是为了分配大小:字符串
第二次是对中:
型
解释:
~(alignment - 1)
是offset
的 * 求反 *(记住,int offset = alignment - 1;
),它给了你掩码,你需要满足对齐请求。算术上,加上偏移量,并执行 * 按位和 *(&
)与它的求反,给你对齐指针的地址。这个算法是如何工作的?首先,请记住,对
malloc()
的内部调用是针对required_bytes + offset
字节的。例如,不是您要求的对齐。例如,你想分配10个字节,对齐方式为16(所以所需的行为是分配从可被16整除的地址开始的10个字节)。所以上面的malloc()
将给予10+16-1
= 25个字节。不一定从正确的地址开始,因为它可以被16整除。但是这个16-1
是0x000F
,它的反(~
)是0xFFF0
。现在我们像这样应用 * 和 *:p + 15 & 0xFFF0
,这将导致每个指针p
都是16的倍数。**但是等等,为什么要首先添加
alignment - 1
的偏移量?你这样做是因为一旦你得到malloc()
返回的地址p
,你唯一不能做的事(为了找到最近的对齐地址)是在 *p
之前查找它--因为这将越过malloc()
调用分配的内存范围,从p
开始。为此,您首先添加alignment - 1
,想想看,正好是你必须前进的最大值。注1:对于这种方式,对齐必须是2的幂。此代码段不强制执行此类操作,因此可能会导致意外行为。
注2:一个有趣的问题是,如何使用此函数的返回值为这样的分配实现
free()
版本。