为什么第一个 sbrk 的 return 值与后续调用不同?

Why is the return value of the first sbrk different than subsequent calls?

我想了解内存在 C 中的工作原理,所以现在正在试验 sbrk 函数。我知道sbrk(0)应该return当前程序break,也就是数据段的结尾。

所以我尝试多次调用 sbrk(0),但出于某种原因,我得到的第一个值与其他值不同。比如这个程序

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

int main()
{
        void * currpb = sbrk(0);
        printf("The current program break is: %p.\n", currpb);

        void * newpb = sbrk(0);
        printf("The current program break is: %p.\n", newpb);

        void *new2pb = sbrk(0);
        printf("The current program break is: %p.\n", new2pb);

        void *new3pb = sbrk(0);
        printf("The current program break is: %p.\n", new3pb);
}

给我以下输出:

The current program break is: 0x18b0000.
The current program break is: 0x18d1000.
The current program break is: 0x18d1000.
The current program break is: 0x18d1000.

我不确定为什么第一个值与其他三个值不同,有什么想法吗?

当您执行 printf 时,它是 calling/using malloc,它将自己调用 sbrk/brk 以分配一些 space 并添加它到内存 heap/pool.

第一个要分配一些space,所以sbrk值就上去了。后续的可以重用 space,因此他们不会再做自己的 sbrk。但是,他们现在的 sbrk 值已被第一个 printf 调用扰乱。

如果您使用 write 并将输出保存到一个文件并使用十六进制编辑器检查它,您不会遇到同样的问题。所有值都相同:

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

int
main()
{
    void *pb;

    pb = sbrk(0);
    write(1,&pb,sizeof(pb));

    pb = sbrk(0);
    write(1,&pb,sizeof(pb));

    pb = sbrk(0);
    write(1,&pb,sizeof(pb));

    pb = sbrk(0);
    write(1,&pb,sizeof(pb));

    return 0;
}

这是十六进制输出:

00000000: 00908401 00000000 00908401 00000000  ................
00000010: 00908401 00000000 00908401 00000000  ................

另一种 [更简单] 的查看方式是在没有干预的情况下执行所有 sbrk 调用 printf:

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

int
main()
{
    void *pb[4];

    for (int idx = 0;  idx < 4;  ++idx)
        pb[idx] = sbrk(0);

    for (int idx = 0;  idx < 4;  ++idx)
        printf("pb=%p sbrk=%p\n",pb[idx],sbrk(0));

    return 0;
}

这个输出是:

pb=0xc42000 sbrk=0xc42000
pb=0xc42000 sbrk=0xc63000
pb=0xc42000 sbrk=0xc63000
pb=0xc42000 sbrk=0xc63000