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;
}
编译以下代码时:
 printf("%10p\n", sbrk(0));
我收到警告提示:
format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’
问题1:为什么?
在我之后malloc(1024 * 1024),程序突破似乎没有改变.
这是输出:
9b12000
9b12000
9b12000
问题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;
}
它可能sbrk会更清楚,不会改变.给我们的记忆malloc被映射到一个完全不同的位置.
你也可以使用strace在Linux上看到调用了哪些系统,并找出malloc使用mmap进行分配.
malloc不限于sbrk用于分配内存。例如,它可能用于mmap映射一大块MAP_ANONYMOUS内存;通常mmap会分配一个远离数据段的虚拟地址。
还有其他的可能性。尤其是,malloc作为标准库的核心部分,本身并不仅限于标准库函数;它可以利用特定于操作系统的接口。
小智 5
如果你malloc在你的代码中使用,它会brk()在开头调用,从堆中分配0x21000字节,这就是你打印的地址,所以问题1:malloc从预分配空间可以满足以下s要求,所以这些malloc实际上没有调用brk,是中的优化malloc。如果下次您想将 malloc 大小超出该边界,brk则会调用一个新的(如果不大于mmap阈值)。