Forum: Mikrocontroller und Digitale Elektronik Was ist der Stack genau...?


von A. Arndt (Gast)


Lesenswert?

Hallo,

kann mir jemand die Funktion der Stack-Tiefe bei FASTAVR erklären, was
trägt man warum hier ein, ich denke, es ist Reservierung im RAM für
Variablen, aber warum steht dieser meist bei 32 bei z.B. Mega und nicht
auf z.B. 128, ich habe jetzt komische Fehler beim Umgang mit Variablen,
die Erhöhung des Stack-Wertes soll helfen...

Gruss
A. Arndt

von Christof Krüger (Gast)


Lesenswert?

Kann zu FASTAVR nicht wirklich was sagen, aber mal allgemein zum Stack:
Wenn du ein Unterprogramm aufrufst, dann muss der µC sich merken, wo er
danach wieder zurückspringen muss. Also wird auf den "Stack", zu
deutsch "Stapel", die Rücksprungadresse gelegt. Lokale Variablen
werten ebenso auf den Stack gelegt und dort verwendet. Wenn das
Unterprogramm beendet ist, werden alle lokalen Variablen wieder vom
Stapel genommen (ihr Gültigkeitsbereich ist hiermit beendet), die
Rücksprungadresse wird gelesen und angesprungen, das Unterprogramm ist
hiermit beendet.
Wenn du viele lokale Variablen oder viele verschachtelte Aufrufe hast,
kann es sein, dass der Stack stark anwächst. Wie gesagt: Ich weiss
jetzt nicht, was 32 oder 128 bei "Stacktiefe" bedeuten soll, aber
wenn das die Anzahl der Worte ist, die der Stack fassen kann, dann
sollte schnell klar werden, dass man mit den Ressourcen sparsam umgehen
soll und evtl. globale Variablen benutzen sollte, wenn dies angebracht
ist und Speicher sparen kann, oder eben die Stack-Größe erweitern.

von Tobi (Gast)


Lesenswert?

wichtig wäre noch, dass der stack von oben nach unten wächst - also vom
ram ende aus. wenn er zu gross wird kann er andere sachen im ram
überschreiben (globale variablen etc.)
probleme kann es halt bei vielen verschachtelten funktionsaufrufen mit
vielen/grossen parametern kommen oder rekursionen usw..

von crazy horse (Gast)


Lesenswert?

Ersteinmal soll der Stack nur so gross wie nötig sein, um nicht unnötig
RAM zu blockieren, der Platz fehlt sonst evtl. für Variablen.
Aber das Problem liegt daran, zu erkennen, wie gross der Stack denn nun
wirklich sein muss, dass kann kein Compiler erkennen. Ein Stack-Überlauf
führt normalerweise zum Absturz und kann von üblichen MCs auch nicht
erkannt werden.
In erster Linie belasten Funktionsaufrufe und Interrupts den Stack, bei
Funktionsaufrufen wird zumindest die Rückkehradresse, manchmal auch die
Parameterübergabe über den Stack realisiert, meist wird dazu jedoch ein
gesonderter Datenstack benutzt. Interruptroutinen sind im Prinzip ja
auch Funktionsaufrufe, nur dass man vorher nicht weiss, wann diese
Funktionen aufgerufen werden, also immer mit dem schlimmsten
rechnen...
Kritisch wirds dann, wenn Funktionen mehrfach  wieder andere Funktionen
(oder sich selbst, Rekursion) aufrufen und als i-Tüpfelchen dann noch
ein Int draufknallt.
Der Stacküberlauf überschreibt gnadenlos Variablen, was dann passiert,
kannst du dir selbst vorstellen.
Für den Test kann man sich Stack-end-marker setzen und dann versuchen
in einer Simulation den kritischsten Systemzustand zu erreichen und den
dann erreichten Stackwert als Stackgrösse zu setzen.
Reicht der RAM nicht, diese Bedingung zu erfüllen, muss das Programm
korrigiert werden (Verschachtelungstiefe reduzieren, in kritischen
Fällen die Interrupts sperren).

von Christof Krüger (Gast)


Lesenswert?

Und um es komplett zu machen: Der so genannte "Heap" wächst von unten
nach oben (also von kleinen Speicheradressen zu hohen). Im Heap werden
globale Variablen und dynamisch alokkierter Speicher abgelegt. Entweder
gibt es eine feste Grenze und wenn der Heap oder Stack über diese Grenze
wachsen möchte gibt es einen Heap- resp. Stackoverflow, oder aber die
Grenze ist fließend und das große "Bumm" gibt es, wenn Stack auf Heap
treffen.
Da ich kein Basic (mehr) kann, hier ein Beispiel aus der c-Sprache.
Wird z.B. einer Funktion eine große struct übergeben, dann wird sie
ganz auf den Stack kopiert. Du kannst in deiner Funktion dann darauf
schreiben, wie du lustig bist, ohne den eigentlich übergebenen struct
zu ändern, da du ja auf einer Kopie arbeitest. Wenn du den struct aber
eh nicht änderst, sondern nur ausliest, dann hast du eine unnötige
Kopie gemacht und hättest stattdessen einen Pointer oder eine Referenz
auf das struct übergeben sollen.
Bei Basic gibt es auch eine Entsprechung zu struct, war das record? Und
als Referenz kann man sowas wohl auch übergeben (by ref?).

von A. Arndt (Gast)


Lesenswert?

Hallo,

vielen Dank für Eure Antworten, ich arbeite zwar "nur" mit dem
einfachen Basic, aber ich denke, ich habe verstanden, was Ihr meint...


Gruss
A. Arndt

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.