Der Stack ist der Speicher, der als Zwischenspeicher für einen Ausführungsfaden reserviert ist. Wenn eine Funktion aufgerufen wird, wird ein Block am oberen Rand des Stacks für lokale Variablen und einige Buchungsinformationen reserviert. Wenn diese Funktion zurückkehrt, wird der Block ungenutzt und kann beim nächsten Funktionsaufruf verwendet werden. Der Stack wird immer in einer LIFO (Last In First Out)-Reihenfolge reserviert; der zuletzt reservierte Block ist immer der nächste, der freigegeben wird. Dies macht es wirklich einfach, den Stack zu verfolgen; das Freigeben eines Blocks aus dem Stack ist nichts weiter als die Anpassung eines Zeigers.
Der Heap ist Speicherplatz für die dynamische Zuweisung. Im Gegensatz zum Stack gibt es kein festgelegtes Muster für die Zuweisung und Freigabe von Blöcken aus dem Heap; Sie können einen Block jederzeit zuweisen und ihn jederzeit freigeben. Dies macht es viel komplexer, zu verfolgen, welche Teile des Heaps zu einem bestimmten Zeitpunkt zugewiesen oder frei sind; Es gibt viele benutzerdefinierte Heap-Allokatoren, die die Leistung des Heaps für unterschiedliche Verwendungsmuster optimieren.
Jeder Thread erhält einen Stack, während es in der Regel nur einen Heap für die Anwendung gibt (obwohl es nicht ungewöhnlich ist, mehrere Heaps für verschiedene Arten von Zuweisungen zu haben).
Um Ihre Fragen direkt zu beantworten:
Inwieweit werden sie vom Betriebssystem oder der Laufzeitumgebung der Sprache kontrolliert?
Das Betriebssystem reserviert den Stack für jeden System-Thread, wenn der Thread erstellt wird. Typischerweise wird das Betriebssystem von der Laufzeitumgebung der Sprache aufgerufen, um den Heap für die Anwendung zuzuweisen.
Was ist ihr Anwendungsbereich?
Der Stack ist an einen Thread gebunden, sodass der Stack zurückgewonnen wird, wenn der Thread beendet wird. Der Heap wird normalerweise beim Start der Anwendung von der Laufzeitumgebung zugeordnet und wird beim Beenden der Anwendung (technisch des Prozesses) zurückgewonnen.
Was bestimmt die Größe von jedem von ihnen?
Die Größe des Stacks wird bei der Erstellung eines Threads festgelegt. Die Größe des Heaps wird beim Start der Anwendung festgelegt, kann aber wachsen, wenn Platz benötigt wird (der Zuweiser fordert mehr Speicher vom Betriebssystem an).
Was macht einen schneller?
Der Stack ist schneller, weil das Zugriffsmuster es trivial macht, Speicher von ihm zuzuweisen und freizugeben (ein Zeiger/Ganzzahl wird einfach erhöht oder verringert), während im Heap viel komplexere Buchführung bei einer Zuweisung oder Freigabe involviert ist. Auch wird jedes Byte im Stack sehr häufig wiederverwendet, was bedeutet, dass es tendenziell in den Cache des Prozessors eingemischt wird, was es sehr schnell macht. Ein weiterer Performance-Nachteil für den Heap ist, dass der Heap, als meist globale Ressource, typischerweise mehrfädig sicher sein muss, d.h. jede Zuweisung und Freigabe muss - in der Regel - synchronisiert sein mit "allen" anderen Heap-Zugriffen im Programm.
Eine klare Demonstration:
Bildquelle: <a href="http://vikashazrati.wordpress.com/2007/10/01/quicktip-java-basics-stack-and-heap/" rel="noreferrer">vikashazrati.wordpress.com</a>
5 Stimmen
@mattshane Die Definitionen von Stack und Heap hängen überhaupt nicht von Wert- und Referenztypen ab. Mit anderen Worten, der Stack und Heap können vollständig definiert werden, auch wenn Wert- und Referenztypen niemals existiert hätten. Darüber hinaus ist der Stack nur ein Implementierungsdetail beim Verständnis von Wert- und Referenztypen. Laut Eric Lippert: Der Stack ist ein Implementierungsdetail, Teil Eins.
248 Stimmen
Eine wirklich gute Erklärung finden Sie hier Was ist der Unterschied zwischen einem Stapel und einem Heap?
19 Stimmen
Auch (wirklich) gut: codeproject.com/Articles/76153/… (der Stack-/Heap-Teil)
21 Stimmen
youtube.com/watch?v=clOUdVDDzIM&spfreload=5
5 Stimmen
Verwandte, siehe Stack Clash. Die Stack Clash-Beseitigungen betrafen einige Aspekte von Systemvariablen und Verhaltensweisen wie
rlimit_stack
. Siehe auch Red Hat Problem 14632411 Stimmen
Nicht klar in den Antworten: Für eine Laufzeitumgebung für eine Programmiersprache (z.B. .NET) gibt es pro Thread einen Stack, um Methodenaufrufe/lokale Variablen zu verwalten, und nur einen gemeinsamen Heap für alle Prozesse der Laufzeitumgebung. Der Heap wird vom Garbage Collector überwacht. Die Speicherbereiche der Laufzeitumgebung (Stacks/Heap) sind Teil des zusammenhängenden virtuellen Speichers, der vom Betriebssystem den Prozessen zugewiesen wird (der selbst von physischen RAM-Blöcken in keiner bestimmten Reihenfolge versorgt wird), auf Anforderung der Prozesse. Die Verwirrung um "Stacks" liegt an der Existenz vieler "Stack"-Arten in einem Computer, die nicht mit den Laufzeitumgebungs-Stacks zusammenhängen. Ein "Stack" ist einfach eine LIFO-Speicherstruktur.
0 Stimmen
Wenn Sie eine Simulation sehen möchten, wie der Stapel und der Heap während der Ausführung eines C-Programms aussehen, versuchen Sie C Tutor.
0 Stimmen
Du solltest definitiv dieses Video sehen, das alle oben genannten Antworten klärt youtube.com/watch?v=7O4JPdKjc30