Was ist der unterschied zwischen stack und heap speicher


C++ unterteilt den verfügbaren Speicher in vier Bereiche. Diese sind der

  1. Programmspeicher,
  2. globale Speicher für globale Variable,
  3. Haldenspeicher für die dynamische Speicherverwaltung, und
  4. Stapelspeicher (statische Speicherverwaltung).[1]

Der Programmspeicher beinhaltet, wie der Name schon verrät, das Programm. In zahlreichen Sprachen ist er strikt vom Datenspeicher getrennt. Manche Sprachen erlauben aus programmiertechnischen Gründen keine globalen Variablen. Bei C++ sind diese zwar erlaubt, es wird aber zwischen Programm- und Datenspeicher grundsätzlich unterschieden.

Neben dem Speicher für globale Variable bleiben noch zwei Bereiche für die Daten. Einer dieser Bereiche wird als Stapelspeicher oder kurz Stapel (stack) bezeichnet und wir haben ihn schon häufig in Anspruch genommen. Den zweiten Speicherbereich bezeichnet man als Haldenspeicher oder kurz als Halde (heap). Er dient der dynamischen Speicherverwaltung und wird in diesem Abschnitt umfassend behandelt.

Für den Stapelspeicher gilt immer: Was zuletzt angefordert wurde, muss auch als erstes wieder freigegeben werden (LIFO: Last In – First Out). Wenn Sie innerhalb eines Blocks {;;;} also Variablen anlegen, werden diese auf dem Stack angelegt. Am Ende des Blocks verliert die Variable ihre Gültigkeit und der Speicher wird wieder freigegeben. Wenn Sie nun eine Funktion aufrufen, wird die aktuelle Programmadresse (also die Stelle im Programm, an der die Funktion aufgerufen wird, die sog. „Rücksprungadresse“) auf dem Stapel abgelegt. Innerhalb der Funktionen werden möglicherweise Variablen angelegt, die wiederum auf dem Stapel landen. Dass dies so geschehen soll, wird vom Compiler zur Übersetzungszeit festgelegt und ist somit eine statische Speicherverwaltung. Am Ende der Funktion werden die Speicherbereiche der Variablen wieder freigegeben und das Programm springt zur Rücksprungadresse, die jetzt wieder oben auf dem Stapel liegt. Somit befindet es sich jetzt wieder an der Stelle, an der die Funktion aufgerufen wurde.

Speicher aus der Halde wird nicht geordnet vergeben. Sie können ihn zu einem beliebigen Zeitpunkt anfordern und müssen ihn auch selbst wieder freigeben. Somit kann innerhalb einer Funktion Haldenspeicher angefordert, und nach Beendigung der Funktion ein Objekt, das auf der Halde liegt, weiterhin genutzt werden. Es wird also nicht mit Beendigung der Funktion ungültig. Versucht ein Objekt so, Speicher für sich zu reservieren, wird dieser im Rahmen der sogenannten dynamischen Speicherverwaltung zur Laufzeit festgelegt.

In den folgenden Kapiteln lernen Sie in erster Linie, wie man in C++ mit Haldenspeicher arbeitet.

Effektive Objekte können nur für den aktuellen Gültigkeitsbereich auf dem sog. Stack erstellt werden. Der Stapelspeicher ist ein Speicherbereich für lokale Variablen eines Moduls (statische Speicherverwaltung). Beim Verlassen eines Gültigkeitsbereichs werden diese Objekte automatisch zerstört. Alle vorigen Beispiele in diesem Abschnitt zeigen, wie Objekte auf dem Stack erstellt und zerstört werden. Größere Objekte wie große Speicherblöcke sollten nur in Beispielanwendungen auf dem Stack erstellt werden, denn dieser Bereich ist stark begrenzt und ist ausschließlich für lokale und temporäre Daten gedacht. Moderne Übersetzer begrenzen diesen Bereich auf 1 Megabyte. Wenn Sie größere Objekte auf den Stack legen wollen, müssen Sie die maximale Stackgröße modifizieren! Tun Sie dies nicht, erhalten Sie höchst bemerkenswerte Meldungen von Laufzeitumgebung, Betriebssystem oder Programmabbrüchen.

Auf dem Heap (deutsch: Halde)Bearbeiten

Effektive Objekte können dynamisch und permanent bis zum Ende der Laufzeit des Moduls erstellt werden. Dies erfolgt im sog. Heap. Der Heap entspricht meistens dem nicht vorgespeicherten Datensegment für das gesamte Programm (dynamische Speicherverwaltung). Dazu verwendet man den Operator new. Wenn ein Objekt nicht mehr benötigt wird, muss es bei dieser Variante manuell zerstört werden und zwar mit dem Operator delete. Weiterführende Konzepte wie Smart-Pointer können das Zerstören beim Verlassen von Gültigkeitsbereichen automatisieren. Diese Operatoren kann man auch für Felder verwenden. Dann muss allerdings bei der Zerstörung der Operator delete [] verwendet werden.

Der Heap hat den eklatanten Vorteil, dass die Grenzen des zuteilbaren Speichers nur vom Betriebssystem und der physikalischen Speichermenge gezogen werden und nicht von Compiler- und Linkereinstellungen. Ein weiterer Vorteil ist, dass alle Elemente einer Klasse dann auch auf dem Heap liegen.

Wir verwenden Klasse 'a' aus vorigem Beispiel:

int main(){ A *pObjekt(0); // Zeiger auf ein A-Objekt pObjekt = new A; // Instanziieren auf dem Heap, Standardkonstruktor verwenden delete pObjekt; // Zerstören char *pszMemory = new char[0x100000]; // 1 Megabyte auf dem Heap allozieren delete [] pszMemory; // Speicherblock wieder freigeben A *ar_Objekte = new A[50]; // 50 Objekte von A anlegen delete [] ar_Objekte; return 0; }

Weitere Optionen zur Verwendung von new, delete, new [] und delete [] gibt es auch.

  1. 7.9 — The stack and the heap (Zugriff 2011-06-17)

Ein Stack ist eine Datenstruktur, die verwendet wird, um Daten in einer bestimmten Reihenfolge zu speichern. Zwei Operationen, die auf einem Stack ausgeführt werden können, umfassen eine Push-Operation, die ein Element in den Stack einfügt, und eine Pop-Operation, die das letzte Element entfernt, das in den Stack hinzugefügt wurde. Es folgt der Reihenfolge Last In First Out (LIFO). Jedes Mal, wenn ein Element hinzugefügt wird, wird es oben auf den Stapel gelegt und das einzige Element, das entfernt werden kann, ist das Element ganz oben im Stapel, genau wie ein Stapel von Objekten. Der Stapel befindet sich im Überlaufzustand, wenn er vollständig voll ist, und im Unterlaufzustand, wenn er vollständig leer ist.

Stack kann einfach mit einem Array oder einer Linked List implementiert werden. Arrays sind schnell, aber in der Größe begrenzt, und die verknüpfte Liste erfordert einen Overhead zum Zuordnen, Verknüpfen, Aufheben und Aufheben der Zuordnung, ist jedoch in der Größe nicht beschränkt.

Was ist der unterschied zwischen stack und heap speicher
Was ist der unterschied zwischen stack und heap speicher
  • Stack bereinigt das Objekt automatisch.
  • Es ermöglicht die Steuerung der Speicherzuweisung und -aufhebung.
  • Es ist schwierig, die Größe der Variablen zu ändern.
  • Ein Stack wird verwendet, wenn eine Variable außerhalb dieser Funktion nicht verwendet wird.
  • Der Stapel ist nicht leicht zu beschädigen.
  • Mit Stack ist es möglich, die Daten in der Methode Last in First out (LIFO) zu verwalten, was bei verknüpften Listen und Arrays nicht möglich ist.
  • Der Stack-Speicher ist sehr begrenzt.
  • Normalerweise besteht die Gefahr eines Stapelüberlaufs, wenn zu viele Objekte auf dem Stapel erstellt werden.
  • Random Access ist mit Stack normalerweise nicht möglich.
  • Bei Stack können Fälle von abnormaler Beendigung auftreten, da Stack normalerweise außerhalb des Speicherbereichs liegt.
  • Der Variablenspeicher wird überschrieben und dies kann zu undefiniertem Verhalten des Programms führen.

Anwendung des Stapels

  • Parsing
  • Ausdruckskonvertierung (Infix zu Postfix, Postfix zu Präfix usw.).

Heap ist ein Spezialfall einer ausgeglichenen binären Baumdatenstruktur, bei der der Wurzelknotenschlüssel mit seinen Kindern verglichen und entsprechend angeordnet wird. Ein Heap respektiert nämlich die Heap-Eigenschaft: Jeder Knoten muss niedriger sein als jeder seiner Kinder oder sein unterstes Element an seiner Wurzel, um leicht zugänglich zu sein .

Um einen binären Baum wie einen Heap darzustellen, besteht eine Implementierung darin, für jeden Knoten eine dynamische Zuordnung vorzunehmen, wobei 2 Zeiger auf seine Kinder zeigen. Ein Haufen kann auch durch die Darstellung in der Form einer realisiert werden Arrays , durch eine tun Ebene um Traversal des Haufens , wobei die Anordnung mit dem Element an der Wurzel beginnt, folgt dann mit den Kindern von dieser Wurzel, dann alle Kinder diese Kinder und dann die Urenkel und so weiter.

Vorteile der Verwendung von Heap

  • Heap hat eine unbegrenzte Speichergröße.
  • Es ermöglicht den globalen Zugriff auf Variablen.
  • Heap-Methode, die auch in der proprietären Warteschlange verwendet wird.
  • Heap hilft, die größte und minimale Anzahl zu finden.
  • Um den vom Objekt verwendeten Speicher freizugeben, wird die Garbage Collection im Heap-Speicher ausgeführt.

Nachteile der Verwendung von Heap

  • Es kann den maximalen Speicher bereitstellen, den ein Betriebssystem bereitstellen kann.
  • Es dauert im Vergleich zum Stack viel Zeit in der Ausführung.
  • Die Speicherverwaltung ist etwas komplex, da sie global verwendet wird.

Der Unterschied

  1. In Stapeln gespeicherte Variablen sind nur für den Thread des Besitzers sichtbar, während im Heap erstellte Objekte für alle Threads sichtbar sind. Einfach ausgedrückt ist Stack-Speicher eine Art privater Speicher von Java-Threads, während Heap-Speicher von allen Threads gemeinsam genutzt wird.
  2. Heap ist eine hierarchische Datenstruktur, während Stack eine lineare Datenstruktur ist.
  3. Heap kann unter Verwendung von Arrays und Bäumen implementiert werden, während ein Stack auf drei Arten implementiert werden kann: basierend auf verknüpften Listen, dynamischem Speicher oder einfach auf Arrays.
  4. Ein Heap ist flexibel und der zugewiesene Speicher kann geändert werden. Andererseits ist Stack nicht flexibel; die zugewiesene Speichergröße kann nicht geändert werden.
  5. Stack-Speicher wird verwendet, um lokale Variablen und Funktionsaufrufe zu speichern, während Heap-Speicher verwendet wird, um Objekte in Java zu speichern. Unabhängig davon, wo das Objekt im Code erstellt wird, beispielsweise als Membervariable, lokale Variable oder Klassenvariable, werden sie in Java immer innerhalb des Heapspace erstellt.
  6. Der Stack-Frame-Zugriff ist einfacher als der Heap-Frame, da der Stack einen kleinen Speicherbereich hat und Cache-freundlich ist, aber im Fall von Heap-Frames, die über den Speicher verteilt sind, führt dies zu mehr Cache-Fehlversuchen.
  7. In einem Stack erfolgt die Zuweisung und Aufhebung der Zuweisung durch die CPU, während im Heap die Zuweisung und Aufhebung der Zuweisung durch den Programmierer manuell erfolgen muss.
  8. Fast alle Baumoperationen können auf Heaps angewendet werden. Ein Element häufen, Minimum finden und Maximum finden. Auf der anderen Seite sind Push, Pop und Top die einzigen Operationen auf dem Stack.
  9. Im Heap gibt es keinen Überlauf und Unterlauf, während wir im Stack die Stack-Größe begrenzen können, so dass Stack-Überlauf- und Stack-Unterlauf-Bedingungen auftreten. Wenn wir ein Element aus dem leeren Stack herausnehmen möchten, wird diese Situation als Stack-Unterlauf bezeichnet. Auf der anderen Seite, wenn wir ein Element auf einen vollen Stack verschieben möchten (Stack-Elemente gleich der Stack-Größe), wird die Situation als Stack-Überlauf bezeichnet.
  10. Stack ist threadspezifisch, während Heap anwendungsspezifisch ist.
  11. Die Handhabung des Haufenrahmens ist kostspieliger als die Handhabung des Stapelrahmens.

Lesen Sie weiter: Verfahren vs. Objekt orientierte Programmierung

Stapel vs. Haufen in Tabellenform

VERGLEICHSGRUNDLAGE  STAPELHAUFEN
Sichtbarkeit von Variablen/ObjektenIn Stapeln gespeicherte Variablen sind nur für den Thread des Besitzers sichtbar.Im Heap erstellte Objekte sind für alle Threads sichtbar.
StrukturtypStack ist eine lineare Datenstruktur.    Heap ist eine hierarchische Datenstruktur.  
ImplementierungStack kann auf drei Arten implementiert werden: basierend auf verketteten Listen, dynamischem Speicher oder einfach auf Arrays.  Heap kann mithilfe von Arrays und Bäumen implementiert werden.
FlexibilitätStapel ist nicht flexibel; die zugewiesene Speichergröße kann nicht geändert werden.Ein Heap ist flexibel und der zugewiesene Speicher kann geändert werden.  
VerwendenHeap-Speicher wird verwendet, um Objekte in Java zu speichern.Stapelspeicher wird verwendet, um lokale Variablen und Funktionsaufrufe zu speichern.
BetretenDer Stack-Frame-Zugriff ist einfacher als der Heap-Frame, da der Stack einen kleinen Speicherbereich hat und Cache-freundlich ist.Der Zugriff auf Heap-Frames ist etwas schwieriger als auf den Stack-Frame, da Heap-Frames über den Speicher verteilt sind und daher mehr Cache-Fehltreffer verursachen.  
Zuweisung und AufhebungIn einem Stack erfolgt die Zuweisung und Aufhebung der Zuweisung durch die CPU.Im Heap muss die Zuweisung und Aufhebung der Zuweisung vom Programmierer manuell vorgenommen werden.  
BetriebPush, Pop und Top sind die einzigen Operationen auf dem Stack.  Fast alle Baumoperationen können auf Heaps angewendet werden. Ein Element häufen, Minimum finden und Maximum finden.
Überlauf und UnterlaufIm Stack können wir die Stack-Größe begrenzen, sodass Stack-Überlauf- und Stack-Unterlauf-Bedingungen auftreten.Es gibt keinen Fall von Überlauf und Unterlauf im Heap.
BesonderheitHeap ist anwendungsspezifisch.Stack ist threadspezifisch.    
KostenDie Handhabung des Stapelrahmens ist weniger kostspielig als die Handhabung des Haufenrahmens.  Die Handhabung des Haufenrahmens ist kostspieliger als die Handhabung des Stapelrahmens.