In der Informatik bezeichnet ein Stack eine häufig - FB2

Werbung
Stack
• In der Informatik bezeichnet ein Stack eine häufig
eingesetzte Datenstruktur.
• Sie wird von den meisten Mikroprozessoren in
Hardware direkt unterstützt.
• Ein Stack wird manchmal auch als Stapelspeicher
oder Kellerspeicher (kurz Stapel oder Keller)
bezeichnet.
30.03.2006
Dr. Jörg Gruner
1
Stack
• Funktionsprinzip
– Ein Stapel kann eine (definierte) Menge von Objekten
aufnehmen und gibt diese entgegengesetzt zur Reihenfolge
der Aufnahme wieder zurück.
– Dabei wird nach dem Last In – First Out – Prinzip
• deutsch: zuletzt hinein und zuerst heraus
• LIFO
gearbeitet, das heißt es wird immer das Objekt aus dem
Stapel zurückgegeben, welches als letztes hineingelegt
wurde.
– Nicht zu verwechseln mit einer Warteschlange
(First In – First Out – Prinzip).
30.03.2006
Dr. Jörg Gruner
2
Stack
• Funktionsprinzip
– Ein Stapelspeicher ist mit einen Stapel von Umzugskisten
vergleichbar.
– Es kann immer eine neue Kiste oben auf den Stapel gepackt
werden oder eine Kiste von oben heruntergenommen
werden.
– Der Zugriff ist immer nur auf das oberste Element des
Stapels möglich.
– Ein Hinzufügen oder Entfernen einer Kiste weiter unten im
Stapel ist nicht möglich.
30.03.2006
Dr. Jörg Gruner
3
Stack
• Funktionsprinzip
– Beim Stack spricht man von automatischer
Speicheranforderung.
– Die Laufzeitkosten einer automatischen
Speicheranforderung sind in der Regel deutlich geringer als
die bei der dynamischen Speicheranforderung (Heap).
– Allerdings ist bei intensiver Nutzung durch sehr große oder
sehr viele Anforderungen der für den Stack reservierte
Speicher bald aufgebraucht.
– In diesem Fall droht ein Programmabbruch wegen
Stapelüberlauf (Stack-Overflow).
30.03.2006
Dr. Jörg Gruner
4
Stack
• Funktionsprinzip
– Stapel stellen die Operationen
• push (einkellern) zum Hinzufügen eines Objektes und
• pop (auskellern) zum Zurückholen und Entfernen eines
Objektes
bereit. Außerdem steht oft der Operator
• peek (nachsehen) zum Holen eines Objektes ohne es zu
entfernen
zur Verfügung.
30.03.2006
Dr. Jörg Gruner
5
Stack
30.03.2006
Dr. Jörg Gruner
6
Stack
• Anwendungen
– Mikroprozessoren
• In Mikroprozessoren gibt es oft ein spezielles Register, den
Stackpointer (Stapelzeiger).
• Dieses Register enthält eine Speicheradresse, die auf den
obersten Stapeleintrag zeigt.
• Wenn mit der Operation push ein weiteres Objekt auf dem
Stapel abgelegt wird, erhöht sich der Wert des Stapelzeigers
und zeigt so auf die nächste Adresse, in die ein weiterer neuer
Stapeleintrag geschrieben wird.
• Bei pop wird der Eintrag der Adresse gelesen und
anschließend der Stapelzeiger vermindert, so dass er auf den
letzten Stapeleintrag zeigt.
• Der Stackpointer kann im Allgemeinen auch direkt gesetzt
werden.
• In manchen Prozessoren wird der Stapelzeiger bei push
vermindert und bei pop erhöht. Am Prinzip ändert dies aber
nichts.
30.03.2006
Dr. Jörg Gruner
7
Stack
• Anwendungen
– Mikroprozessoren
• Der Stapel des Mikroprozessors wird oft von diesem selbst bei
Aufruf und Rücksprung von Unterprogrammen zur Speicherung
der Rücksprungadresse genutzt, ohne dass ein zusätzliches
push oder pop zum Ablegen oder Holen dieser
Rücksprungadresse nötig ist, da die entsprechenden
Anweisungen das Register selbst richtig setzen.
• In Multitasking-Systemen gibt es für jedes Programm einen
eigenen Stapelspeicher. Beim Umschalten zwischen
Prozessen wird dieser durch direktes Setzen des Stapelzeigers
initialisiert.
30.03.2006
Dr. Jörg Gruner
8
Stack
• Anwendungen
– Programmiersprachen
• Compiler für moderne Programmiersprachen nutzen
gewöhnlich push- und pop-Operationen vor dem Aufruf eines
Unterprogramms, um an dieses Parameter zu übergeben.
• Ähnlich können so auch Ergebnisse eines Unterprogrammes
zurückgegeben werden.
• Lokale Variablen, zum Beispiel von Unterprogrammen, können
ebenfalls auf dem Stapel gespeichert werden.
• Für die rekursive Programmierung wird dieser Mechanismus
erweitert, da für die lokalen Variablen der Unterprogramme
gegebenenfalls enormer Platz benötigt wird. Anderenfalls
besteht die Gefahr des Stack-Overflow.
30.03.2006
Dr. Jörg Gruner
9
Stack
• Anwendungen
– Compiler
• Zur Übersetzung des Quellcodes einer Formalen Sprache
nutzen Compiler und Interpreter einen Parser, der bei der
Textanalyse Syntax-Regeln auf einem Stapel ablegt und so
vergleichend dem nachfolgenden Textelement eine
angenommene Bedeutung (das oberste Stapelelement)
zuordnen kann.
• Die Verwendung eines Stapelspeichers zur Übersetzung von
Programmiersprachen wurde 1957 von Friedrich Ludwig Bauer
und Klaus Samelson unter dem Namen "Kellerprinzip"
patentiert. Die internationale Anerkennung und Ehrung ihrer
Leistung erfolgte erst im Jahre 1988.
• Programmiersprachen, die auf einer virtuelle Maschine
aufsetzen (zum Beispiel Java, C#), optimieren den kompilierten
Zwischencode für die Verwendung eines Stapels, um zur
Laufzeit die Interpretation dieses Zwischencodes zu
beschleunigen.
30.03.2006
Dr. Jörg Gruner
10
Stack
•
Anwendungen
– Verarbeitung von Klammerstrukturen
• Stapelspeicher eignen sich auch zur Auswertung von
Klammerausdrücken, wie sie etwa in der Mathematik geläufig sind.
– Dabei wird zunächst für Operatoren und Operanden je ein Stapelspeicher
initialisiert.
– Der zu verarbeitende Klammerausdruck wird nun symbolweise eingelesen.
– Wird eine öffnende Klammer eingelesen, so ist diese zu ignorieren.
– Wird ein Operand oder Operator eingelesen, so ist dieser auf den jeweiligen
Stapelspeicher zu legen.
– Wird eine schließende Klammer eingelesen, so wir der oberste Operator
vom Stapelspeicher für die Operatoren genommen und entsprechend
diesem Operator eine geeignete Anzahl von Operanden, die zur
Durchführung der Operation benötigt werden.
– Das Ergebnis wird dann wieder auf dem Stapelspeicher für Operanden
abgelegt.
– Sobald der Stapelspeicher für die Operatoren leer ist, befindet sich im
Stapelspeicher für die Operanden das Ergebnis.
30.03.2006
Dr. Jörg Gruner
11
Stack
• Anwendungen
– Postfixnotation
• Zur Berechnung von Termen wird gelegentlich die
Postfixnotation verwendet, die mit Hilfe der Operationen eine
Klammersetzung und Prioritätsregeln für die Operationen
überflüssig macht.
• Zahlwerte werden automatisch auf dem Stapel abgelegt.
– binäre Operatoren (zum Beispiel +, −, *, /) holen die oberen
beiden Werte
– unäre Operatoren (zum Beispiel Vorzeichenwechel) einen Wert
vom Stapel und
– legen anschließend das (Zwischen-)Ergebnis dort wieder ab.
30.03.2006
Dr. Jörg Gruner
12
Stack
• Anwendungen
– Infixnotation
• Bei der maschinengestützten Auflösung von arithmetischen
Ausdrücken in der so genannten Infixnotation
– der Operator steht zwischen den beteiligten Zahlwerten
werden zunächst vorrangige Teilterme in einem Stapel
zwischengelagert und so faktisch der Infix-Term schrittweise in
einen Postfix-Term umgewandelt, bevor das Ergebnis durch
Abarbeiten des Stapels errechnet wird.
30.03.2006
Dr. Jörg Gruner
13
Stack
• Anwendungen
– Stapelorientierte Sprachen
• Stapelorientierte Sprachen (z. B. Forth oder Postscript) wickeln
fast alle Variablen-Operationen über einen Stapel ab und
stellen neben den oben genannten Operatoren noch weitere
zur Verfügung. Beispielsweise tauscht der Forth-Operator swap
die obersten beiden Elemente des Stapels. Arithmetische
Operationen werden in der Postfix-Notation aufgeschrieben
und beeinflussen damit ebenfalls den Stapel.
• Forth benutzte einen zweiten Stapel (Return-Stapel) zur
Zwischenspeicherung der Rücksprungadressen von
Unterprogrammen während der Ausführungsphase. Dieser
Stapel wird auch während der Übersetzungsphase für die
Adressen der Sprungziele für die Kontrollstrukturen verwendet.
Die Übergabe und Rückgabe von Werten an Unterprogrammen
geschieht über den ersten Stapel, der zweite nimmt die
Rücksprungadresse auf.
30.03.2006
Dr. Jörg Gruner
14
Heap
•
In der Informatik bezeichnet der Heap
– engl. Halde oder Haufen
einen Speicherbereich.
•
Programme fordern zur Laufzeit zusammenhängende
Speicherabschnitte aus dem Heap an und geben diese in beliebiger
Reihenfolge wieder frei.
•
Deshalb wird der Heap auch als dynamischer Speicherbereich oder als
Freispeicher bezeichnet.
•
Die Freigabe kann sowohl manuell als auch mit Hilfe einer
automatischen Speicherbereinigung (Garbage-Collection) erfolgen.
•
Eine Speicheranforderung vom Heap bzw. Freispeicher wird auch
dynamische Speicheranforderung genannt.
•
Der Heap wird im Unterschied zum Stack von der Hardware nicht
unterstützt.
30.03.2006
Dr. Jörg Gruner
15
Heap
• Unterstützung von dynamischen
Speicheranforderungen in Programmiersprachen
– Programmiersprachen unterstützen die dynamische
Speicheranforderung auf unterschiedliche Weisen.
• In ISO-C gibt es dafür beispielsweise die Funktion malloc().
• Mit der Funktion free() wird der Speicher wieder freigegeben.
• In ISO-C++ gibt es weiterhin die Möglichkeit, Speicher
dynamisch mit Hilfe von new() anzufordern und mit delete()
wieder freizugeben.
30.03.2006
Dr. Jörg Gruner
16
Heap
• Verwaltung des Heap durch die Laufzeitumgebung
bzw. das Betriebssystem
– siehe Kapitel „Speicherverwaltung“ der Vorlesung
30.03.2006
Dr. Jörg Gruner
17
Herunterladen