16

我试图理解这个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);
}

4

1 回答 1

11

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

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

第一次printf调用malloc内部调用以分配缓冲区stdoutstdout默认情况下是行缓冲的,但缓冲区是在您第一次打印到它时按需创建的)。

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

这个答案没有直接关系,但是来自 valgrind 的错误消息暴露了malloc隐藏在里面的底层调用的存在printf。)

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

于 2019-01-21T19:36:19.627 回答