【发布时间】:2015-08-13 01:53:11
【问题描述】:
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()的手册页中找到。
【问题讨论】:
-
#include <unistd.h>? -
@JS1 是的,解决了这个问题,你能解释一下吗,我是 linux 编程新手...
-
您需要
sbrk()的原型,它位于unistd.h中。如果没有原型,编译器会假定未知函数返回int。 -
@JS1 是的,我以为
sbrk()是在stdlib.h中声明的,谢谢! -
@EricWang:如果您使用 -Wall 编译(假设您使用 gcc 或 clang),它会发出警告。您应该始终使用 -Wall 进行编译。
标签: c memory-management malloc mmap sbrk