Forum: Compiler & IDEs Heap / Stack Kollision?


von Stefan (Gast)


Lesenswert?

Guten Abend,

ich hätte eine Frage bezüglich Heap und Stack; ich verwender malloc für 
einen FIFO Buffer. Wird der FIFO langsamer geleert als gefüllt wächst 
der Heap vom unteren Adressbereich natürlich immer weiter an in Richtung 
Stack, bis schließlich malloc 0 zurück gibt. Woher weiß aber malloc wann 
Schluss ist? Die Größe des Stacks kann malloc nicht kennen und es darf 
auch nicht bis zum oberen Ende gehen, weil irgendwo definitiv der Stack 
beginnt. Ich gehe daher davon aus, dass irgendwo definiert sein muss wie 
weit der Heap wachsen darf. Ist das richtig, und wenn ja wo, und vor 
allem wie kann ich den Wert ggf anpassen? Und was passiert eigentlich 
wenn der Heap den Stack küsst aber noch mehr auf den Stack muss? 
Überschreibt der Stack einfach gnadenlos meinen Heap oder weiß der Stack 
dass darunter Speicher vergeben ist und wenn letzteres was passiert 
dann?
Sorry für die vielen Fragen, aber das interessiert mich gerade wirklich 
brennend!

Gruß
Stefan

von Markus E. (engelmarkus)


Lesenswert?

http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Nutzung_des_SRAM_durch_avr-gcc

> Heap und Stack müssen sich den Speicher, der nicht von .data, .bss und .noinit 
belegt ist, teilen

> Wird der Stackbereich zu groß, weil dort zu viele Daten abgelegt werden  [...] 
dann überschreibt man damit womöglich andere Daten und es kommt zur Fehlfunktion 
des Programmes. Gleiches gilt, wenn die Obergrenze des Heap über der Untergrenze 
des Stabels hinauswächst.

Das sollte eigentlich alles erklären. Weder der Heap noch der Stack 
wissen voneinander :) .
Lies auch mal bei "Dynamischer RAM-Verbrauch" weiter. Vielleicht ist das 
__builtin_alloca was für dich?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wass pasiert ist abhängig von der Hardware. Es ist zB nicht überall so, 
daß Stack auf den Heap folgt oder überhaupt ein linearer Speicher 
vorhanden ist.

Ein Mechanismus ist, daß malloc _sbrk aufruft, um vom OS neuen Speicher 
anzufordern. Je nach implementierung überprüft sbrk gegen das vom Linker 
definierte Symbol _end/end.

Hier eine Implementierung in der libnosys

http://sourceware.org/cgi-bin/cvsweb.cgi/src/libgloss/libnosys/sbrk.c?rev=1.4&content-type=text/x-cvsweb-markup&cvsroot=src

und für SPU
http://sourceware.org/cgi-bin/cvsweb.cgi/src/libgloss/spu/sbrk.c?rev=1.4&content-type=text/x-cvsweb-markup&cvsroot=src

auf Systemen mit OS wird dann ein Syscall ausgeführt, und das OS kümmert 
sich darum. Idr ist es einer Task nicht erlauft, neuen Speicher zu 
nehmen, aber diese kann ihn vom OS -- das dann mit erweiterten Rechten 
läuft -- anfordern.

von Stefan (Gast)


Lesenswert?

Hallo Markus,

schönen Dank für das Dokument, sehr interessant!
Ich habe mir nun einfach damit geholfen das Symbol heap_end zu 
überschreiben:

LDFLAGS += -Wl,--defsym=__heap_end=0x800900

Lieber wäre mir gewesen irgendwie das Symbol __malloc_margin 
hochzusetzten (ist stadardmäßig auf 32 gesetzt), aber das hat leider 
nicht geklappt. Nun begrenze ich die Heapgröße einfach so dass mehr 
Platz für den Stack ist.

Gruß
Stefan

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan schrieb:
> Lieber wäre mir gewesen irgendwie das Symbol __malloc_margin
> hochzusetzten (ist stadardmäßig auf 32 gesetzt), aber das hat leider
> nicht geklappt.

Muss gehen.  __malloc_margin ist aber eine Variable, die muss man
zur Laufzeit zuweisen.  Im Gegensatz zu den expliziten Heapgrenzen
kann man __malloc_margin auch beliebig während der Laufzeit verändern.

von Stefan (Gast)


Lesenswert?

Achso, ich hab's im makefile versucht, vielen Dank!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.