Warum ergibt der zweimalige Aufruf von sbrk(0) einen anderen Wert?

Lesezeit: 2 Minuten

Benutzer-Avatar
Bibas

Ich versuche das zu verstehen sbrk() Funktion.

Von dem was ich weiß:
sbrk(0) gibt die aktuelle Adresse der Unterbrechung zurück und erhöht sie nicht.
sbrk(size) erhöht die Adresse des Breaks um size Bytes und gibt die vorherige Adresse des Breaks zurück.

Also habe ich etwas erstellt, um es zu testen:

#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
}

Ich erwarte also ein Ergebnis, das wie folgt aussieht:

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

aber stattdessen bekomme ich das:

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

Warum nicht die ersten beiden Anrufe von sbrk(0) denselben Wert zurückgeben? Was passiert zwischen diesen beiden Aufrufen, die die Unterbrechungsadresse ändern?

BEARBEITEN :
Das Speichern von Adressen in Variablen löst das Problem:

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);
}

  • printf könnte etwas dynamisches Speichermaterial verwenden. Versuchen Sie stattdessen, die Werte Variablen zuzuweisen, und drucken Sie sie sofort aus.

    – Eugen Sch.

    21. Januar 2019 um 17:09 Uhr


  • Dann aktualisieren Sie Ihre Frage bitte auch mit dem anderen Code, damit niemand diese Annahme wiederholt.

    – Eugen Sch.

    21. Januar 2019 um 17:24 Uhr

  • Sie müssen verwenden mehrere Variablen, und tun alle Anrufe zu sbrk vor dem Anruf printf. Ihr aktualisierter Code funktioniert im Grunde genauso wie der erste und wird das gleiche Problem haben.

    – Irgendein Programmierer-Typ

    21. Januar 2019 um 17:32 Uhr

  • Mein erraten ist, dass die Initialisierung der Standard-E/A-Teile träge erfolgt. Das heißt, die Initialisierung erfolgt, wenn sie benötigt werden, und ein Teil dieser Initialisierung ist die Zuweisung des Puffers für stdout.

    – Irgendein Programmierer-Typ

    21. Januar 2019 um 17:50 Uhr

  • Hier ist der Argumentbehandlungscode von glibc: github.com/bminor/glibc/blob/master/stdio-common/… Es ruft malloc() an einigen Stellen.

    – Rumpelsepp

    21. Januar 2019 um 17:50 Uhr


Ihr Programm führt die folgende Aufruffolge aus:

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

Der erste Anruf bei printf Anrufe malloc intern, um einen Puffer für zuzuweisen stdout (stdout ist standardmäßig zeilengepuffert, aber der Puffer wird bei Bedarf erstellt, wenn Sie zum ersten Mal darauf drucken).

Deshalb der zweite Aufruf an sbrk gibt einen anderen Wert zurück.

(Diese Antwort steht nicht in direktem Zusammenhang, aber die Fehlermeldungen von valgrind zeigen die Existenz des zugrunde liegenden malloc Rufen Sie im Inneren versteckt printf.)

Ihr zweites Beispiel führt alle aus sbrk Aufrufe im Voraus, sodass es keine Überraschungen durch Aufrufe anderer Funktionen gibt malloc hinter deinem Rücken.

1101200cookie-checkWarum ergibt der zweimalige Aufruf von sbrk(0) einen anderen Wert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy