Unterschied zwischen statischer und dynamischer Speicherzuordnung

Antworten:

90

Es gibt drei Arten der Zuordnung: statisch, automatisch und dynamisch.

Statische Zuordnung bedeutet, dass der Speicher für Ihre Variablen beim Programmstart zugewiesen wird. Die Größe wird beim Erstellen des Programms festgelegt. Dies gilt für globale Variablen, Dateibereichsvariablen und Variablen, die mit staticdefinierten internen Funktionen qualifiziert sind.

Die automatische Speicherzuweisung erfolgt für (nicht statische) Variablen, die in Funktionen definiert sind, und wird normalerweise auf dem Stapel gespeichert (obwohl der C-Standard nicht vorschreibt, dass ein Stapel verwendet wird). Sie müssen keinen zusätzlichen Speicher reservieren, haben jedoch auch eine eingeschränkte Kontrolle über die Lebensdauer dieses Speichers. Beispiel: Automatische Variablen in einer Funktion sind nur vorhanden, bis die Funktion beendet ist.

void func() {
    int i; /* `i` only exists during `func` */
}

Die dynamische Speicherzuordnung ist etwas anders. Sie steuern jetzt die genaue Größe und Lebensdauer dieser Speicherorte. Wenn Sie es nicht freigeben, treten Speicherlecks auf, die zum Absturz Ihrer Anwendung führen können, da das System zu einem bestimmten Zeitpunkt nicht mehr Speicher zuweisen kann.

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

Im oberen Beispiel ist der zugewiesene Speicher weiterhin gültig und zugänglich, obwohl die Funktion beendet wurde. Wenn Sie mit dem Speicher fertig sind, müssen Sie ihn freigeben:

free(mem);
Constantinius
quelle
2
Sicher haben Sie die Kontrolle über die Lebensdauer der Variablen ... Sie entscheiden über den Umfang, oder?
Luchian Grigore
Natürlich, aber das habe ich nicht gemeint. Sie können die Lebensdauer der Variablen nicht verlängern, um ihren Umfang zu überleben. Aber vielleicht sollte ich das in meiner Antwort klarstellen. Danke
Constantinius
5
-1 Diese Antwort ist falsch. Sie verwechseln statische und automatische Variablen.
Brice
2
Ihr eigener Satz lautet: " Statische Zuordnung bedeutet, dass der Speicher für Ihre Variablen automatisch zugewiesen wird". Dies ist falsch . Schauen Sie sich an, was die Handbuchseite für GNUs libc dazu zu sagen hat.
Brice
1
@EliBendersky Es wird jetzt umformuliert. Überprüfen Sie, ob es jetzt korrekt ist.
Suraj Jain
113

Dies ist eine Standard-Interviewfrage:

Dynamische Speicherzuordnung

Sind Speicher zur Laufzeit zugewiesen mit calloc(), malloc()und Freunde. Es wird manchmal auch als ‚Halde‘ Speicher bezeichnet, obwohl es nichts mit der Heap - Datenstruktur zu tun ref .

int * a = malloc(sizeof(int));

Der Heapspeicher bleibt bestehen, bis er free()aufgerufen wird. Mit anderen Worten, Sie steuern die Lebensdauer der Variablen.

Automatische Speicherzuordnung

Dies wird allgemein als "Stapel" -Speicher bezeichnet und wird zugewiesen, wenn Sie einen neuen Bereich eingeben (normalerweise, wenn eine neue Funktion auf den Aufrufstapel übertragen wird). Sobald Sie den Bereich verlassen, sind die Werte der automatischen Speicheradressen undefiniert, und es ist ein Fehler, auf sie zuzugreifen .

int a = 43;

Beachten Sie, dass Umfang nicht unbedingt Funktion bedeutet. Bereiche können innerhalb einer Funktion verschachtelt werden, und die Variable befindet sich nur innerhalb des Blocks, in dem sie deklariert wurde. Beachten Sie auch, dass nicht angegeben ist, wo dieser Speicher zugewiesen ist. (Auf einem vernünftigen System befindet es sich auf dem Stapel oder registriert sich zur Optimierung.)

Statische Speicherzuordnung

Wird zur Kompilierungszeit * zugewiesen , und die Lebensdauer einer Variablen im statischen Speicher entspricht der Lebensdauer des Programms .

In C kann statischer Speicher mithilfe des staticSchlüsselworts zugewiesen werden . Der Bereich ist nur die Kompilierungseinheit.

Interessanter wird es, wenn das externSchlüsselwort berücksichtigt wird . Wenn eine externVariable definiert ist, weist der Compiler ihr Speicher zu. Wenn eine externVariable deklariert wird , muss der Compiler die Variable an anderer Stelle definieren . Wenn externVariablen nicht deklariert / definiert werden, treten Verknüpfungsprobleme auf, während Fehler beim Deklarieren / Definieren von staticVariablen zu Kompilierungsproblemen führen.

Im Dateibereich ist das statische Schlüsselwort optional (außerhalb einer Funktion):

int a = 32;

Aber nicht im Funktionsumfang (innerhalb einer Funktion):

static int a = 32;

Technisch gesehen externund staticsind zwei getrennte Klassen von Variablen in C.

extern int a; /* Declaration */
int a; /* Definition */

* Hinweise zur statischen Speicherzuordnung

Es ist etwas verwirrend zu sagen, dass statischer Speicher zur Kompilierungszeit zugewiesen wird, insbesondere wenn wir bedenken, dass der Kompilierungscomputer und der Hostcomputer möglicherweise nicht identisch sind oder sich nicht einmal auf derselben Architektur befinden.

Es ist möglicherweise besser zu glauben, dass die Zuweisung des statischen Speichers vom Compiler übernommen wird, als zur Kompilierungszeit .

Zum Beispiel kann der Compiler einen großen dataAbschnitt in der kompilierten Binärdatei erstellen und wenn das Programm in den Speicher geladen wird, die Adresse innerhalb derdataDas Segment des Programms wird als Speicherort für den zugewiesenen Speicher verwendet. Dies hat den deutlichen Nachteil, dass die kompilierte Binärdatei sehr groß wird, wenn viel statischer Speicher verwendet wird. Es ist möglich, eine Multi-Gigabyte-Binärdatei zu schreiben, die aus weniger als einem halben Dutzend Codezeilen generiert wird. Eine andere Möglichkeit besteht darin, dass der Compiler Initialisierungscode einfügt, der den Speicher auf andere Weise zuweist, bevor das Programm ausgeführt wird. Dieser Code variiert je nach Zielplattform und Betriebssystem. In der Praxis verwenden moderne Compiler Heuristiken, um zu entscheiden, welche dieser Optionen verwendet werden sollen. Sie können dies selbst ausprobieren, indem Sie ein kleines C-Programm schreiben, das ein großes statisches Array von 10k-, 1m-, 10m-, 100m-, 1G- oder 10G-Elementen zuweist. Bei vielen Compilern wächst die Binärgröße linear mit der Größe des Arrays und über einen bestimmten Punkt hinaus.

Speicher registrieren

Die letzte Speicherklasse sind 'Register'-Variablen. Wie erwartet sollten Registervariablen im Register einer CPU zugewiesen werden, aber die Entscheidung bleibt tatsächlich dem Compiler überlassen. Sie dürfen eine Registervariable nicht mithilfe von address-of in eine Referenz umwandeln.

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

Die meisten modernen Compiler sind schlauer als Sie, wenn es darum geht, welche Variablen in die Register aufgenommen werden sollen :)

Verweise:

brice
quelle
3
Hinweis: Ich würde int * a = malloc(sizeof(*a));stattdessen vorschlagen , die Wiederholung von zu vermeiden a. Dies macht die Sache viel einfacher, wenn überhaupt die Art der aÄnderungen.
Shahbaz
1
Eigentlich heißt es Heap, hat aber nichts mit der Heap-Datenstruktur zu tun. Haufen bedeutet in diesem Fall einen unordentlichen Ort
dynamisch
2
„Statische Speicherzuweisung ... Ist bei der Kompilierung zugewiesen“ Wollen Sie damit sagen Zuordnungsgröße wird bestimmt bei der Kompilierung? Würde die Speicherfreigabe nicht nur zur Laufzeit erfolgen?
lf215
2

Statische Speicherzuordnung: Der Compiler weist den erforderlichen Speicherplatz für eine deklarierte Variable zu. Durch Verwendung der Adresse des Operators wird die reservierte Adresse erhalten und diese Adresse kann einer Zeigervariablen zugewiesen werden. Da die meisten deklarierten Variablen statischen Speicher haben, ist dies der Fall Die Zuweisung eines Zeigerwerts zu einer Zeigervariablen wird als statische Speicherzuordnung bezeichnet. Speicher wird während der Kompilierungszeit zugewiesen.

Dynamische Speicherzuordnung: Es werden Funktionen wie malloc () oder calloc () verwendet, um Speicher dynamisch abzurufen. Wenn diese Funktionen zum dynamischen Abrufen von Speicher verwendet werden und die von diesen Funktionen zurückgegebenen Werte Zeigervariablen zugewiesen werden, werden solche Zuweisungen als dynamischer Speicher bezeichnet Zuordnung.Speicher wird zur Laufzeit zugewiesen.

Rajeev Kumar
quelle
2

Statische Speicherzuordnung:

  • Variablen werden dauerhaft zugeordnet
  • Die Zuordnung erfolgt vor der Programmausführung
  • Es verwendet die aufgerufene Datenstruktur Stack bezeichnete zur Implementierung der statischen Zuordnung
  • Weniger effizient
  • Es gibt keine Wiederverwendbarkeit des Speichers

Dynamische Speicherzuordnung:

  • Variablen werden nur zugewiesen wenn die Programmeinheit aktiv wird
  • Die Zuordnung erfolgt während Programmausführung
  • Es verwendet die Datenstruktur namens Heap zur Implementierung der dynamischen Zuordnung
  • Effizienter
  • Es gibt Speicherwiederverwendbarkeit . Speicher kann freigegeben werden, wenn er nicht benötigt wird
vinay
quelle
1
"Static Memory Allocation [...] Es verwendet die als Stack bezeichnete Datenstruktur zur Implementierung der statischen Zuordnung." Nein , das ist falsch und irreführend. In meinem Beitrag finden Sie den Unterschied zwischen automatischer und statischer Zuordnung. Der statische Speicher kann den Stapel verwenden. Dies ist stark implementierungsabhängig und es können mehrere Strategien für dieselbe Implementierung verwendet werden. Ich bin mir auch nicht sicher, was Sie unter "weniger effizient" verstehen. @Trieu Toan, Sie haben die Bedeutung dieser Antwort mit einer schlechten Bearbeitung geändert.
Brice
1

Unterschied zwischen STATIC MEMORY ALLOCATION und DYNAMIC MEMORY ALLOCATION

Der Speicher wird zugewiesen, bevor die Ausführung des Programms beginnt (während der Kompilierung).
Während der Ausführung des Programms wird Speicher zugewiesen.

Während der Ausführung werden keine Speicherzuweisungs- oder Freigabeaktionen ausgeführt.
Speicherbindungen werden während der Ausführung hergestellt und zerstört.

Variablen bleiben permanent zugeordnet.
Wird nur zugewiesen, wenn die Programmeinheit aktiv ist.

Implementiert mit Stacks und Heaps.
Implementiert mit Datensegmenten.

Für den Zugriff auf Variablen wird ein Zeiger benötigt.
Keine dynamisch zugewiesenen Zeiger erforderlich.

Schnellere Ausführung als dynamisch.
Langsamere Ausführung als statisch.

Mehr Speicherplatz erforderlich.
Weniger Speicherplatz erforderlich.

Ebenezer
quelle
1
Die statische Speicherzuweisung wird auf dem Stapel zugewiesen, während die dynamische Speicherzuweisung auf dem Heap
Usman Kurd am
@UsmanKurd Das ist im Allgemeinen falsch in Bezug auf den statischen Speicher. Siehe meine Antwort.
Brice
0

Der statischen Speicherzuweisung wird Speicher zugewiesen, bevor das Programm während der Kompilierungszeit ausgeführt wird. Die dynamische Speicherzuordnung ist der zugewiesene Speicher während der Programmausführung zur Laufzeit.

Ritu Maheswari
quelle
-1

Statische Speicherzuordnung. Der zugewiesene Speicher befindet sich im Stapel.

int a[10];

Dynamische Speicherzuordnung. Der zugewiesene Speicher befindet sich im Heap.

int *a = malloc(sizeof(int) * 10);

und letzteres sollte frei sein d, da es in C keinen Garbage Collector (GC) gibt.

free(a);
onemach
quelle