musl libc malloc 中的 adjust_size 是做什么的?
What adjust_size in musl libc malloc does?
我正在研究 musl libc malloc
实现,但我很难理解 adjust_size
函数。
static int adjust_size(size_t *n)
{
/* Result of pointer difference must fit in ptrdiff_t. */
if (*n-1 > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE) {
if (*n) {
errno = ENOMEM;
return -1;
} else {
*n = SIZE_ALIGN;
return 0;
}
}
*n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
return 0;
}
例如在第一个比较中,为什么他们不只是与 PTRDIFF_MAX
进行比较。无论如何,这似乎是上面评论的意图,为什么他们要从 *n
中减去 1,我认为 (*n-1)
被比较为无符号而不是有符号,所以他们正在处理这个案例其中 *n
为 0。但我不知道为什么在那种情况下将其作为无符号进行比较,因为看起来两个位置最后都会计算为有符号数。
另外,如果 *n
为 0,为什么他们将其设置为 SIZE_ALIGN
?我的理解是 malloc 应该 return NULL
或一个指针,如果大小为 0,它可以传递给 free 而不会引起问题。
why they are not just comparing against PTRDIFF_MAX
大多数 malloc
实现使用 mmap
单独分配大块。因为 mmap
以页为单位分配内存,所以 n
需要与页边界对齐 (PAGE_SIZE
),另外还应包括块头(按 SIZE_ALIGN
对齐)。
这就是为什么要对 PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE
而不是 PTRDIFF_MAX
进行比较的原因 - 以确保所有可能的未来对齐调整不会导致块大小大于 PTRDIFF_MAX
。
why are they subtracting 1 from *n
因为n
以后可能会这样对齐:
n = (n + SIZE_ALIGN + PAGE_SIZE - 1) & -PAGE_SIZE;
结果值应小于或等于 PTRDIFF_MAX
。值PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE + 1
还可以,所以减1。
Also why does they set *n
to SIZE_ALIGN
if it is 0
因为调整后的块大小应该大于或等于 SIZE_ALIGN
字节以适应 OVERHEAD
字节的堆开销加上请求的数据区域应该能够适应以后从 [=30= 使用的 2 个指针].稍后在代码中采用这种对齐方式。
I think that (*n-1)
was being compared as unsigned instead of
signed, so they are handling the case where *n
is 0. But I do not
know why this is being compared as unsigned in that case as it seems
both positions would evaluate to signed numbers at the end.
我觉得可以写得简单一点(虽然这可能不正确,我可能需要睡觉了):
static int adjust_size(size_t *n)
{
if (*n > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE + 1) {
errno = ENOMEM;
return -1;
}
*n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
return 0;
}
我正在研究 musl libc malloc
实现,但我很难理解 adjust_size
函数。
static int adjust_size(size_t *n)
{
/* Result of pointer difference must fit in ptrdiff_t. */
if (*n-1 > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE) {
if (*n) {
errno = ENOMEM;
return -1;
} else {
*n = SIZE_ALIGN;
return 0;
}
}
*n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
return 0;
}
例如在第一个比较中,为什么他们不只是与 PTRDIFF_MAX
进行比较。无论如何,这似乎是上面评论的意图,为什么他们要从 *n
中减去 1,我认为 (*n-1)
被比较为无符号而不是有符号,所以他们正在处理这个案例其中 *n
为 0。但我不知道为什么在那种情况下将其作为无符号进行比较,因为看起来两个位置最后都会计算为有符号数。
另外,如果 *n
为 0,为什么他们将其设置为 SIZE_ALIGN
?我的理解是 malloc 应该 return NULL
或一个指针,如果大小为 0,它可以传递给 free 而不会引起问题。
why they are not just comparing against
PTRDIFF_MAX
大多数 malloc
实现使用 mmap
单独分配大块。因为 mmap
以页为单位分配内存,所以 n
需要与页边界对齐 (PAGE_SIZE
),另外还应包括块头(按 SIZE_ALIGN
对齐)。
这就是为什么要对 PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE
而不是 PTRDIFF_MAX
进行比较的原因 - 以确保所有可能的未来对齐调整不会导致块大小大于 PTRDIFF_MAX
。
why are they subtracting 1 from
*n
因为n
以后可能会这样对齐:
n = (n + SIZE_ALIGN + PAGE_SIZE - 1) & -PAGE_SIZE;
结果值应小于或等于 PTRDIFF_MAX
。值PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE + 1
还可以,所以减1。
Also why does they set
*n
toSIZE_ALIGN
if it is 0
因为调整后的块大小应该大于或等于 SIZE_ALIGN
字节以适应 OVERHEAD
字节的堆开销加上请求的数据区域应该能够适应以后从 [=30= 使用的 2 个指针].稍后在代码中采用这种对齐方式。
I think that
(*n-1)
was being compared as unsigned instead of signed, so they are handling the case where*n
is 0. But I do not know why this is being compared as unsigned in that case as it seems both positions would evaluate to signed numbers at the end.
我觉得可以写得简单一点(虽然这可能不正确,我可能需要睡觉了):
static int adjust_size(size_t *n)
{
if (*n > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE + 1) {
errno = ENOMEM;
return -1;
}
*n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
return 0;
}