为什么两次调用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. 【示例二】的代码,为什么输出是正确的?
    sbrk在 printf 之前调用,因此,其他函数的 malloc 是在分配空间之后进行,不会对输出结果造成影响。


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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容