Größe des Stack- und Heap-Speichers [duplicate]

Lesezeit: 6 Minuten

Benutzeravatar von Vivek Maran
Vivek Maran

Mögliches Duplikat:

Was und wo sind Stapel und Haufen?

In Bezug auf die grundlegenden Konzepte des Speicherlayouts in einem AC-Programm verstehe ich Folgendes:

  • Die Sprache verwendet zwei primäre Datenstrukturen Stapel und Haufen.
  • Stack wird erstellt, um die lokalen Variablen und Buchhaltungsdaten von Subroutinen zu speichern
  • Heap wird erstellt, um die dynamisch zugewiesenen Variablen des Programms zu speichern
  • Heap ist von Natur aus von variabler Länge. (Nicht sehr sicher auf Stack)
  • Normalerweise liegt es in der Verantwortung des Compilers/der Sprache, das Betriebssystem aufzufordern, diese Datenstrukturen vor der Ausführung zu erstellen.

Fragen

  • Was ist die Anfangsgröße, mit der ein Stack/Heap erstellt wird? und wer entscheidet darüber?
  • In welchem ​​physikalischen Gedächtnis werden sie geschaffen? Ich sehe eine allgemeine Beschreibung als “Stack wird in der Top-Level-Adresse und der Heap in der Low-Level-Adresse erstellt” Bitte erläutern Sie dies

Benutzeravatar von Steve Jessop
Steve Jessop

“Stack wird in der Top-Level-Adresse und der Heap in der Low-Level-Adresse erstellt” Bitte erläutern Sie dies

Dies ist ein Mythos. Es mag eine Grundlage in der historischen Wahrheit haben. Es kann manchmal mit Dingen übereinstimmen, die Sie im wirklichen Leben sehen. Aber es ist nicht wörtlich wahr.

Es ist jedoch leicht genug zu erkunden:

#include <stdlib.h>
#include <stdio.h>

void check(int depth) {
    char c;
    char *ptr = malloc(1);
    printf("stack at %p, heap at %p\n", &c, ptr);
    if (depth <= 0) return;
    check(depth-1);
}

int main() {
    check(10);
    return 0;
}

Auf meiner Maschine sehe ich:

stack at 0x22ac3b, heap at 0x20010240
stack at 0x22ac0b, heap at 0x200485b0
stack at 0x22abdb, heap at 0x200485c0
stack at 0x22abab, heap at 0x200485d0
stack at 0x22ab7b, heap at 0x200485e0
stack at 0x22ab4b, heap at 0x200485f0
stack at 0x22ab1b, heap at 0x20048600
stack at 0x22aaeb, heap at 0x20048610
stack at 0x22aabb, heap at 0x20048620
stack at 0x22aa8b, heap at 0x20048630
stack at 0x22aa5b, heap at 0x20048640

Der Stapel geht also nach unten und der Haufen nach oben (wie Sie es aufgrund des Mythos erwarten könnten), aber der Stapel hat die kleinere Adresse und sie wachsen nicht aufeinander zu (Mythos gesprengt).

Übrigens, meine check Die Funktion ist endrekursiv, und bei einigen Implementierungen mit einigen Compileroptionen sehen Sie möglicherweise, dass sich der Stapel überhaupt nicht bewegt. Das sagt Ihnen etwas darüber aus, warum der Standard nicht vorschreibt, wie all dies funktioniert – wenn dies der Fall wäre, könnte er versehentlich nützliche Optimierungen verbieten.

  • Die Endrekursion eliminiert den aktuellen Stapelrahmen, bevor der rekursive Aufruf erfolgt, da er nach dem Ende des rekursiven Aufrufs nicht benötigt wird. Stack geht immer noch nach unten, es passiert einfach in diesem Fall, es besteht keine Notwendigkeit, den Stack zu vergrößern.

    – Benutzer1706991

    15. Februar 2016 um 18:53 Uhr

  • Es ist kein Mythos. Ihre Programmausgabe auf modernen Nicht-ASLR Linux: stack at 0x7fff356d5fd7, heap at 0x1d39010. Tun sudo bash -c 'for x in /proc/*/maps; do echo $x; egrep stack\|heap $x; done' zeigt sich für alle Prozesse ähnlich. Als Exploit wurde 2014 eine Stack/Heap-Kollision verwendet: “Der Effekt all dieser Befehlszeilenargumente besteht darin, sowohl den Stack (der nach unten wächst) als auch den Heap (der nach oben wächst) aufzublähen, bis sie miteinander kollidieren.”

    – Bain

    4. Juli 2016 um 16:26 Uhr


  • Die Tatsache, dass es ein System gibt, auf dem die Aussage wahr ist, hindert sie nicht daran, ein Mythos zu sein, wenn sie wie in der Frage als “allgemeine Beschreibung” präsentiert wird. Es ist eine Möglichkeit, es zu tun, aber die allgemeine Behauptung, dass es “so ist, wie es gemacht wird”, ist einfach falsch.

    – Steve Jessop

    14. Juli 2016 um 23:11 Uhr


Benutzeravatar von fkl
fkl

Wie bereits erwähnt, sind Größen betriebssystemspezifisch. Für zB Windows mit Visual Studio beträgt die Standardstapelgröße 1 MB

msdn

Unter Linux kann der folgende Befehl Ihren aktuellen anzeigen.

ulimit -s or -a

Auf meinem Linux Mint 64 Bit zeigt es 8192 KB.

Jedes in den Speicher geladene Programm hat mehrere Segmente. In der Assemblierung kann man jeden davon mit dem Präfix .data, .code usw. angeben (intelx86).

Es ist ein Datensegment, das mehrere Unterabschnitte hat. Sowohl Stack als auch Heap gehören neben einigen anderen dazu.

Der Stack kann auch implizit wachsen, dh wenn Sie einen weiteren Funktionsaufruf machen, wird ein Aktivierungsdatensatz auf den Stack geschoben, wodurch mehr Speicher des Stacks verwendet wird. Aus diesem Grund führt die unendliche Rekursion zu einem Absturz, wenn ein Programm keinen zugewiesenen Stapel mehr hat.

Wenn ein Funktionsaufruf zurückkehrt, wird dieser Aktivierungsdatensatz entfernt und der Stapel verkleinert.

Im Gegensatz dazu wächst Heap aus der entgegengesetzten Richtung und enthält den gesamten dynamisch zugewiesenen Speicher.

Der Grund, warum diese beiden Segmente in entgegengesetzter Richtung wachsen, besteht darin, die Nutzung ihres kombinierten Speichers zu maximieren. Beachten Sie, dass dies, wie in den Kommentaren erwähnt, kein AC-Standard ist, aber die meisten gängigen Betriebssysteme haben dies implementiert.

—— Stack beginnt ———– Stack wächst nach unten

——– Wenn sie sich nicht kreuzen, kann ein Programm ausgeführt werden.

——- Haufen beginnt ————Haufen wächst nach oben

Wenn Ihr Programm keinen Heap verwendet, kann Ihr Stack den maximalen Speicher einschließlich des Heap verwenden. Wenn das Programm nur wenige rekursive Aufrufe durchführt und ein Minimum an lokalen Variablen verwendet (dh weniger Speicher für den Stapel verwendet), kann es den Heap am meisten nutzen.

Andere Teile des Datensegments sind BSS usw., die Felder wie nicht initialisierte statische Variablen enthalten können

  • Die Richtung der Stack/Heap-Expansion ist nicht durch den C-Standard spezifiziert. Sie können sowohl nach oben als auch nach unten wachsen und es wäre vom Standard erlaubt.

    – Alexey Frunze

    2. Oktober 2012 um 9:12 Uhr

  • Einverstanden. Das ist eine gängige Implementierung zB unter Linux. Aber wie gesagt, kein AC-Standard

    – fkl

    2. Oktober 2012 um 9:15 Uhr


  • Danke für die Antwort!! Zusätzlich möchte ich das folgende “ulimit” zitieren, das die Obergrenze der Stapelgröße anzeigt (nicht die vom Compiler verwendete). Ich nehme an, dass das Programm nach dieser Grenze mit einem Stapelüberlauffehler endet

    – Vivek Maran

    2. Oktober 2012 um 11:28 Uhr

Was ist die Anfangsgröße, mit der ein Stack/Heap erstellt wird? und wer entscheidet darüber?

Dies ist Compiler- und OS-spezifisch.

In welchem ​​physikalischen Gedächtnis werden sie geschaffen? Ich sehe eine allgemeine Beschreibung als “Heap wird in der Top-Level-Adresse erstellt und in der Low-Level-Adresse gestapelt”.

Dies ist Compiler- und OS-spezifisch.

Wirklich. Der Sprachstandard schreibt weder die minimale Stack-Größe vor, noch gibt er den Speicherort des Stacks oder des Heaps im Speicher an. Und der Grund dafür ist, C-Programme weniger abhängig von diesen Details zu machen und damit besser auf verschiedene Plattformen portierbar zu machen (sprich: verschiedene Betriebssysteme, verschiedene CPUs, verschiedene Compiler).

Zunächst stellt der C-Standard keine Anforderungen, wie der Stack/Heap von der Plattform implementiert wird.

What is the initial size with which a stack/heap is created? and who decides it?

Typischerweise eine feste Größe von Stapel wird jedem Prozess vom Betriebssystem plattformspezifisch zugewiesen. Es gibt keine Begrenzung der Heap-Größe, Programme haben normalerweise den gesamten verfügbaren virtuellen Adressraum.

Wherein physical memory are they are created?

Dies ist plattformspezifisch. Typischerweise wächst der Stack nach unten und der Heap nach oben.

1412630cookie-checkGröße des Stack- und Heap-Speichers [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy