malloc() - 它是否使用brk()或mmap()

Eri*_*ang 16 c malloc memory-management mmap sbrk

c代码:

// program break mechanism
// TLPI exercise 7-1

#include <stdio.h>
#include <stdlib.h>

void program_break_test() {
    printf("%10p\n", sbrk(0));

    char *bl = malloc(1024 * 1024);
    printf("%x\n", sbrk(0));

    free(bl);
    printf("%x\n", sbrk(0));

}

int main(int argc, char **argv) {
    program_break_test();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译以下代码时:

 printf("%10p\n", sbrk(0));
Run Code Online (Sandbox Code Playgroud)

我收到警告提示:

format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’

问题1:为什么?


在我之后malloc(1024 * 1024),程序突破似乎没有改变.

这是输出:

9b12000
9b12000
9b12000
Run Code Online (Sandbox Code Playgroud)

问题2:进程在启动以备将来使用时是否在堆上分配内存?或者编译器改变分配的时间点?否则,为什么?


[更新]摘要:brk()或mmap()

在查看TLPI并检查手册页(在TLPI的作者的帮助下)之后,现在我了解了如何malloc()决定使用brk()mmap(),如下所示:

mallopt()可以设置参数来控制行为malloc(),并且M_MMAP_THRESHOLD通常有一个名为的参数:

  • 如果请求的内存小于它,brk()将被使用;
  • 如果请求的内存大于或等于它,mmap()将被使用;

参数的默认值是128kb(在我的系统上),但是在我的测试程序中我使用了1Mb,因此mmap()选择了,当我将请求的内存更改为32kb时,我看到了brk()会被使用.

书中提到TLPI第147页和第1035页,但我没有仔细阅读该部分.

参数的详细信息可以在手册页中找到mallopt().

Jay*_*nek 12

如果我们改变程序以查看malloc内存的位置:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void program_break_test() {
  printf("%10p\n", sbrk(0));

  char *bl = malloc(1024 * 1024);
  printf("%10p\n", sbrk(0));
  printf("malloc'd at: %10p\n", bl);

  free(bl);
  printf("%10p\n", sbrk(0));

}

int main(int argc, char **argv) {
  program_break_test();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它可能sbrk会更清楚,不会改变.给我们的记忆malloc被映射到一个完全不同的位置.

你也可以使用strace在Linux上看到调用了哪些系统,并找出malloc使用mmap进行分配.


ric*_*ici 6

malloc不限于sbrk用于分配内存。例如,它可能用于mmap映射一大块MAP_ANONYMOUS内存;通常mmap会分配一个远离数据段的虚拟地址。

还有其他的可能性。尤其是,malloc作为标准库的核心部分,本身并不仅限于标准库函数;它可以利用特定于操作系统的接口。

  • sbrk 在特定位置分配内存;每次调用“sbrk”时,您都会获得与上一次调用相邻的一块内存。从历史上看,这是堆和堆栈之间的边界(堆从数据段向上生长,而堆栈从进程地址空间的末尾向下生长)。mmap 通常不能分配更多内存,但它绝对可以使用不同的地址和更多选项(内存保护标志、后备存储、巨大的虚拟块(以减少页表大小)等)来分配它 (2认同)

小智 5

如果你malloc在你的代码中使用,它会brk()在开头调用,从堆中分配0x21000字节,这就是你打印的地址,所以问题1:malloc从预分配空间可以满足以下s要求,所以这些malloc实际上没有调用brk,是中的优化malloc。如果下次您想将 malloc 大小超出该边界,brk则会调用一个新的(如果不大于mmap阈值)。