美文网首页
为什么两次调用sbrk(0)会得出不同的值?

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

作者: JamFF | 来源:发表于2021-03-28 15:13 被阅读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?

    相关文章

      网友评论

          本文标题:为什么两次调用sbrk(0)会得出不同的值?

          本文链接:https://www.haomeiwen.com/subject/sutycltx.html