为什么两次调用sbrk(0)会得出不同的值?

在学习函数 sbrk() 的时候,我们知道:

void *sbrk (intptr_t increment);
  • 当 increment 为正时,则按 increment 的大小,开辟内存空间,并返回开辟前,程序中断点(program break)的地址。
  • 当 increment 为负时,则按 increment 的大小,释放内存空间,并返回释放前,程序中断点的地址。
  • 当 increment 为零时,不会分配或释放空间,返回当前程序中断点的地址。

那么写一下测试代码,【示例一】:

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

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 <unistd.h>
#include <stdio.h>

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 的锅!

  1. 【示例一】的代码,为什么前两次调用 sbrk(0) 没有返回相同的值?
    在第一次调用 printf 函数时,内部分配一个缓冲区 stdout,创建缓冲器的时候调用了 malloc,而 malloc 内部又调用了 brk 分配内存。

  2. 【示例一】的代码,为什么后面再多次调用 printf 没有产生变化?
    这是因为,默认情况下,stdout 是行缓冲,并且缓冲区是在第一次打印时按需创建的,后面不论多少次调用 printf ,缓冲区都已完成创建。

  3. 【示例二】的代码,为什么输出是正确的?
    sbrkprintf 之前调用,因此,其他函数的 malloc 是在分配空间之后进行,不会对输出结果造成影响。


参考资料:Why does calling sbrk(0) twice give a different value?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章