【发布时间】:2020-08-15 18:30:25
【问题描述】:
在研究Linux操作系统的内存管理时,看到实现对齐的malloc函数的一般方案如下代码:
void *aligned_malloc(size_t required_bytes, size_t alignment) {
void *p1; // original block
void **p2; // aligned block
int offset = alignment - 1 + sizeof(void *);
if ((p1 = (void *)malloc(required_bytes + offset)) == NULL) {
return NULL;
}
p2 = (void **)(((size_t)(p1) + offset) & ~(alignment - 1));
p2[-1] = p1;
return p2;
}
此解决方案存在一个问题,即由于& ~(alignment - 1),它仅在alignment 是2 的幂时才能正常工作。此外,alignment 必须是 size_t 数据类型,以便它适合指针 p1 的数据类型。
由于这些限制,我想到了另一种解决方案:
void *aligned_malloc(size_t required_bytes, size_t alignment) {
void *p1; // original block
void **p2; // aligned block
int offset = alignment - 1 + sizeof(void *);
if ((p1 = (void*)malloc(required_bytes + offset)) == NULL) {
return NULL;
}
offset = (size_t)(p1) % alignment; // offset is used so that I don't have to declare another variable
p2 = (void **)((size_t)(p1) + (alignment - offset));
p2[-1] = p1;
return p2;
}
此解决方案解决了这两个问题,即 alignment 不必既不是 2 的幂也不是 size_t 数据类型。我的问题是,为什么不使用这种实现对齐 malloc 的方式?它有什么缺点让人们选择使用按位运算符& 和~ 的解决方案?
非常感谢任何帮助。谢谢。
【问题讨论】:
-
对于初学者,您的代码不会像原始代码那样在
p2[-1]处为void *留出空间。在您的代码中,p2[-1]可能在malloc返回的块之外,这很糟糕。 -
另外请注意,允许
alignment是 2 的非幂并不是真正有用,因为想要对齐内存块的通常原因是为了更高效的 CPU 操作(或仅允许)在对齐的数据上,并且这些总是2要求的幂。因此,没有人会希望块与 3 或 5 或 13 的倍数对齐,因此没有理由降低代码的效率来支持这一点。
标签: c linux memory-management malloc