在学习函数 sbrk()
的时候,我们知道:
void *sbrk (intptr_t increment);
- 当 increment 为正时,则按 increment 的大小,开辟内存空间,并返回开辟前,程序中断点(program break)的地址。
- 当 increment 为负时,则按 increment 的大小,释放内存空间,并返回释放前,程序中断点的地址。
- 当 increment 为零时,不会分配或释放空间,返回当前程序中断点的地址。
那么写一下测试代码,【示例一】:
#include
#include
int main() {
printf("sbrk(0) = %p\n", sbrk(0)); // 应该返回 x
printf("sbrk(0) = %p\n", sbrk(0)); // 应该返回 x
printf("sbrk(5) = %p\n", sbrk(5)); // 应该返回 x
printf("sbrk(0) = %p\n", sbrk(0)); // 应该返回 x + 5
return 0;
}
预期得到类似这样的结果:
sbrk(0) = 0x1985000
sbrk(0) = 0x1985000
sbrk(5) = 0x1985000
sbrk(0) = 0x1985005
但是输出却是这样的:
sbrk(0) = 0x1985000
sbrk(0) = 0x19a6000
sbrk(5) = 0x19a6000
sbrk(0) = 0x19a6005
换一个写法,将地址存储在变量中,【示例二】:
#include
#include
int main() {
void *toto1 = sbrk(0);
void *toto2 = sbrk(0);
void *toto3 = sbrk(5);
void *toto4 = sbrk(0);
printf("sbrk(0) = %p\n", toto1);
printf("sbrk(0) = %p\n", toto2);
printf("sbrk(5) = %p\n", toto3);
printf("sbrk(0) = %p\n", toto4);
}
输出结果:
sbrk(0) = 0x617000
sbrk(0) = 0x617000
sbrk(5) = 0x617000
sbrk(0) = 0x617005
这才是我们预想的一样,那为什么会出现这种情况呢?
其实出现这个问题的原因:是 printf 的锅!
【示例一】的代码,为什么前两次调用
sbrk(0)
没有返回相同的值?
在第一次调用printf
函数时,内部分配一个缓冲区stdout
,创建缓冲器的时候调用了malloc
,而malloc
内部又调用了brk
分配内存。【示例一】的代码,为什么后面再多次调用
printf
没有产生变化?
这是因为,默认情况下,stdout
是行缓冲,并且缓冲区是在第一次打印时按需创建的,后面不论多少次调用printf
,缓冲区都已完成创建。【示例二】的代码,为什么输出是正确的?
sbrk
在printf
之前调用,因此,其他函数的malloc
是在分配空间之后进行,不会对输出结果造成影响。
参考资料:Why does calling sbrk(0) twice give a different value?