Почему возвращаемое значение первого sbrk отличается от последующих вызовов?

Я пытаюсь понять, как работает память в C, поэтому экспериментирую с sbrk функционировать сейчас. я знаю это sbrk(0) должен вернуть текущий разрыв программы, то есть конец сегмента данных.

Я попытался позвонить 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.

Не уверен, почему 1-е значение отличается от трех других, есть идеи?

1 ответ

Решение

Когда вы делаете printfзвонит / использует malloc, который будет делать свои собственные звонки sbrk/brk выделить некоторое пространство и добавить его в кучу / пул памяти.

Первый должен выделить некоторое пространство, поэтому sbrk ценность возрастает. Последующие могут повторно использовать это пространство, поэтому они не делают свое собственное 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
Другие вопросы по тегам