首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >malloc会不会转到最近的页面大小?

malloc会不会转到最近的页面大小?
EN

Stack Overflow用户
提问于 2021-01-28 05:08:37
回答 2查看 654关注 0票数 2

我不知道我是不是在问什么问题,但我要问的是。我也找了很多类似的问题,但一无所获。

因此,我知道mmapbrk是如何工作的,并且不管输入的长度如何,它都会将其舍入到最近的页面边界。我也知道malloc使用brk/sbrkmmap (至少在Linux/Unix系统上是这样),但这就提出了一个问题:malloc是否也会聚集到最近的页面大小?对我来说,一个页面大小是4096字节,所以如果我想用malloc分配16个字节,那么4096字节就是.比我要求的要多得多。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-28 06:09:58

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>


int main(void) {
    void *a = malloc(1);
    void *b = malloc(1);
    uintptr_t ua = (uintptr_t)a;
    uintptr_t ub = (uintptr_t)b;
    size_t page_size = getpagesize();

    printf("page size: %zu\n", page_size);
    printf("difference: %zd\n", (ssize_t)(ub - ua));
    printf("offsets from start of page: %zu, %zu\n",
        (size_t)ua % page_size, (size_t)ub % page_size);
}

版画

代码语言:javascript
运行
复制
page_size: 4096
difference: 32
offsets from start of page: 672, 704

因此很明显,在中,它不是四舍五入到页面大小,这证明了并不总是四舍五入到页面大小。

如果您将分配更改为任意大的大小,它将命中mmap。例如:

代码语言:javascript
运行
复制
void *a = malloc(10000001);
void *b = malloc(10000003);

我得到了:

代码语言:javascript
运行
复制
page size: 4096
difference: -10002432
offsets from start of page: 16, 16

而且很明显,起始地址仍然没有对齐;簿记必须存储在指针下面,并且指针需要足够对齐以满足通常需要的最大对齐--您可以用free对此进行推理--如果free只是得到一个指针,但它需要知道分配的大小,它可以在哪里查找,并且只有两种选择是可行的:在一个单独的数据结构中,列出所有的基本指针及其分配大小,或者在当前指针下方的某个偏移量。其中只有一个是理智的。

票数 3
EN

Stack Overflow用户

发布于 2021-01-28 07:10:17

malloc和好友的基本工作是管理这样一个事实:操作系统通常只能(有效)处理大量的分配(整个页面和页面的范围),而程序通常需要更小的块和更细粒度的管理。

所以malloc (通常)所做的是,当它第一次被调用时,它会从系统中分配更多的内存(通过mmap或sbrk --可能是一个页面或多个页面),并使用其中的一小部分来跟踪堆的使用情况(堆在哪里,哪些部分在使用,哪些部分是空闲的),然后将其余的空间标记为空闲。然后,它将从该空闲空间分配您请求的内存,并使其余的内存可用于后续的malloc调用。

因此,当您第一次调用malloc (例如16字节)时,它将使用mmap或sbrk分配一个大块(可能是4K或64K,甚至更多),并将其初始化为大部分空闲,并返回一个指向16个字节的指针。第二次调用malloc,再调用16个字节,就会从池中返回另外16个字节--不需要再返回到OS以获得更多信息。

当您的程序继续运行时,将从这个池中调出更多内存,而空闲调用将将内存返回给空闲池。如果它通常分配的比它释放的要多,那么最终空闲池将耗尽,此时malloc将调用系统(mmap或sbrk)以获得更多的内存以添加到空闲池中。

这就是为什么如果您使用某种进程监视器来监视使用malloc/free分配和释放内存的进程,通常只会看到内存使用量上升(因为空闲池耗尽,系统请求更多的内存),并且通常不会看到它关闭--即使内存正在释放,它通常只是返回到空闲池,而不是未映射或返回到系统。有一些异常--特别是如果涉及到非常大的块--但是通常在进程退出之前,您不能依赖任何内存被返回到系统。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65931325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档