Computerwissenschaften

Heap vs. Stack für Delphi-Entwickler

Rufen Sie die Funktion „DoStackOverflow“ einmal aus Ihrem Code auf und Sie erhalten den von Delphi ausgelösten EStackOverflow- Fehler mit der Meldung „Stapelüberlauf“.


funktionieren DoStackOverflow: Integer;

 

Start

 

 Ergebnis:=1 + DoStackOverflow;

 

Ende;

Was ist dieser „Stapel“ und warum gibt es dort einen Überlauf mit dem obigen Code?

Die DoStackOverflow-Funktion ruft sich also rekursiv auf – ohne eine „Exit-Strategie“ – sie dreht sich einfach weiter und wird nie beendet.

Eine schnelle Lösung besteht darin, den offensichtlichen Fehler zu beheben und sicherzustellen, dass die Funktion irgendwann vorhanden ist (damit Ihr Code von der Stelle aus ausgeführt werden kann, an der Sie die Funktion aufgerufen haben).

Sie gehen weiter und blicken nie zurück, ohne sich um den Fehler / die Ausnahme zu kümmern, da dieser jetzt behoben ist.

Es bleibt jedoch die Frage: Was ist dieser Stapel und warum gibt es einen Überlauf ?

 

Speicher in Ihren Delphi-Anwendungen

Wenn Sie mit dem Programmieren in Delphi beginnen, tritt möglicherweise ein Fehler wie der oben beschriebene auf. Sie lösen ihn und fahren fort. Dieser bezieht sich auf die Speicherzuordnung. Meistens interessiert Sie die Speicherzuweisung nicht, solange Sie das, was Sie erstellen, freigeben .

Wenn Sie mehr Erfahrung mit Delphi sammeln, erstellen Sie Ihre eigenen Klassen, instanziieren sie, kümmern sich um die Speicherverwaltung und dergleichen.

Sie werden an den Punkt gelangen, an dem Sie in der Hilfe etwas wie „Lokale Variablen (deklariert in Prozeduren und Funktionen) befinden sich im Stapel einer Anwendung „ lesen werden . Außerdem sind Klassen Referenztypen, sodass sie bei der Zuweisung nicht kopiert, als Referenz übergeben und auf dem Heap zugewiesen werden .

Also, was ist „Stapel“ und was ist „Haufen“?

 

Stapel gegen Haufen

Wenn Sie Ihre Anwendung unter Windows ausführen. befinden sich drei Bereiche im Speicher, in denen Ihre Anwendung Daten speichert: globaler Speicher, Heap und Stapel.

Globale Variablen (ihre Werte / Daten) werden im globalen Speicher gespeichert. Der Speicher für globale Variablen wird von Ihrer Anwendung beim Start des Programms reserviert und bleibt zugewiesen, bis Ihr Programm beendet wird. Der Speicher für globale Variablen wird als „Datensegment“ bezeichnet.

Da der globale Speicher beim Beenden des Programms nur einmal zugewiesen und freigegeben wird, ist dies in diesem Artikel nicht wichtig.

In Stack und Heap findet die dynamische Speicherzuweisung statt: Wenn Sie eine Variable für eine Funktion erstellen, wenn Sie eine Instanz einer Klasse erstellen, wenn Sie Parameter an eine Funktion senden und deren Ergebniswert verwenden / übergeben.

 

Was ist Stapel?

Wenn Sie eine Variable innerhalb einer Funktion deklarieren, wird der zum Speichern der Variablen erforderliche Speicher vom Stapel zugewiesen. Sie schreiben einfach „var x: integer“, verwenden „x“ in Ihrer Funktion und wenn die Funktion beendet wird, kümmern Sie sich weder um die Speicherzuweisung noch um die Freigabe. Wenn die Variable den Gültigkeitsbereich verlässt (Code verlässt die Funktion), wird der auf dem Stapel belegte Speicher freigegeben.

Der Stapelspeicher wird dynamisch unter Verwendung des LIFO-Ansatzes („last in first out“) zugewiesen.

In Delphi-Programmen wird der Stapelspeicher von verwendet

  • Lokale Routinevariablen (Methode, Prozedur, Funktion).
  • Routineparameter und Rückgabetypen.
  • Windows API-Funktionsaufrufe .
  • Datensätze (aus diesem Grund müssen Sie keine Instanz eines Datensatztyps explizit erstellen).

Sie müssen den Speicher auf dem Stapel nicht explizit freigeben, da der Speicher automatisch magisch für Sie zugewiesen wird, wenn Sie beispielsweise eine lokale Variable für eine Funktion deklarieren. Wenn die Funktion beendet wird (manchmal sogar vorher aufgrund der Delphi-Compiler-Optimierung), wird der Speicher für die Variable automatisch freigegeben.

Die Stapelspeichergröße ist standardmäßig groß genug für Ihre (so komplexen) Delphi-Programme. Die Werte „Maximale Stapelgröße“ und „Minimale Stapelgröße“ in den Linker-Optionen für Ihr Projekt geben Standardwerte an – in 99,99% müssten Sie diese nicht ändern.

Stellen Sie sich einen Stapel als einen Stapel von Speicherblöcken vor. Wenn Sie eine lokale Variable deklarieren / verwenden, wählt der Delphi-Speichermanager den Block von oben aus, verwendet ihn und wird, wenn er nicht mehr benötigt wird, an den Stapel zurückgegeben.

Wenn der lokale Variablenspeicher vom Stapel verwendet wird, werden lokale Variablen beim Deklarieren nicht initialisiert. Deklarieren Sie eine Variable „var x: integer“ in einer Funktion und versuchen Sie einfach, den Wert zu lesen, wenn Sie die Funktion eingeben – x hat einen „seltsamen“ Wert ungleich Null. Initialisieren Sie daher immer Ihre lokalen Variablen (oder legen Sie den Wert fest), bevor Sie deren Wert lesen.

Aufgrund von LIFO sind Stapeloperationen (Speicherzuweisung) schnell, da nur wenige Operationen (Push, Pop) erforderlich sind, um einen Stapel zu verwalten.

 

Was ist Haufen?

Ein Heap ist ein Speicherbereich, in dem dynamisch zugeordneter Speicher gespeichert ist. Wenn Sie eine Instanz einer Klasse erstellen, wird der Speicher vom Heap zugewiesen.

In Delphi-Programmen wird der Heapspeicher von / when verwendet

  • Erstellen einer Instanz einer Klasse.
  • Erstellen und Ändern der Größe dynamischer Arrays.
  • Explizites Zuweisen von Speicher mit GetMem, FreeMem, New und Dispose ().
  • Verwenden von ANSI / Wide / Unicode-Zeichenfolgen, Varianten, Schnittstellen (automatisch von Delphi verwaltet).

Der Heap-Speicher hat kein schönes Layout, bei dem es eine Reihenfolge geben würde, in der Speicherblöcke zugewiesen werden. Der Haufen sieht aus wie eine Dose Murmeln. Die Speicherzuordnung vom Heap ist zufällig, ein Block von hier als ein Block von dort. Daher sind Heap-Operationen etwas langsamer als die auf dem Stapel.

Wenn Sie nach einem neuen Speicherblock fragen (dh eine Instanz einer Klasse erstellen), übernimmt Delphi Memory Manager dies für Sie: Sie erhalten einen neuen Speicherblock oder einen gebrauchten und verworfenen.

Der Heap besteht aus dem gesamten virtuellen Speicher ( RAM und Speicherplatz ).

 

Manuelles Zuweisen von Speicher

Jetzt, da alles über den Speicher klar ist, können Sie das oben Gesagte (in den meisten Fällen) ignorieren und einfach weiter Delphi-Programme schreiben, wie Sie es gestern getan haben.

Natürlich sollten Sie wissen, wann und wie Sie Speicher manuell zuweisen / freigeben.

Der „EStackOverflow“ (vom Anfang des Artikels an) wurde ausgelöst, da bei jedem Aufruf von DoStackOverflow ein neues Speichersegment aus dem Stapel verwendet wurde und der Stapel Einschränkungen aufweist. So einfach ist das.

Similar Posts

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.