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

时间:2019-01-21 17:07:01

标签: c memory sbrk brk

我正在尝试了解sbrk()函数。

据我所知:
sbrk(0)返回中断的当前地址,并且不递增。
sbrk(size)将中断的地址增加size个字节,并返回中断的前一个地址。

所以我创建了一些东西来测试它:

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

int main(void)
{
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
    printf("sbrk(5) = %p\n", sbrk(5)); // should return value x
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x + 5
}

所以我期望看到这样的结果:

sbrk(0) = 0x1677000 // x value
sbrk(0) = 0x1677000 // x value
sbrk(5) = 0x1677000 // x value
sbrk(0) = 0x1677005 // x value + 5

但是我得到了这个:

sbrk(0) = 0x1677000 // x value
sbrk(0) = 0x1698000 // y value
sbrk(5) = 0x1698000 // y value
sbrk(0) = 0x1698005 // y value + 5

sbrk(0)的前两个调用为什么不返回相同的值? 在这两个更改中断地址的呼叫之间会发生什么?

编辑: 将地址存储在变量中可以解决问题:

int main(void)
{
    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);
}

1 个答案:

答案 0 :(得分:6)

您的程序执行以下调用序列:

sbrk()
printf()
sbrk()
printf()
...

printf的第一个调用在内部调用malloc来为stdout分配一个缓冲区(stdout默认是行缓冲的,但是该缓冲区是按需创建的,第一个时间打印到它)。

这就是为什么第二次调用sbrk返回不同的值的原因。

({This answer并没有直接关系,但是来自valgrind的错误消息暴露了隐藏在malloc中的底层printf调用的存在。)

您的第二个示例预先执行了所有sbrk调用,因此,其他函数在您的背后调用malloc并不令人惊讶。