Ich möchte wissen, was der Unterschied zwischen statischer und dynamischer Speicherzuordnung ist.
Könnten Sie dies anhand eines Beispiels erklären?
Ich möchte wissen, was der Unterschied zwischen statischer und dynamischer Speicherzuordnung ist.
Könnten Sie dies anhand eines Beispiels erklären?
Antworten:
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 static
definierten 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);
Dies ist eine Standard-Interviewfrage:
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.
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.)
Wird zur Kompilierungszeit * zugewiesen , und die Lebensdauer einer Variablen im statischen Speicher entspricht der Lebensdauer des Programms .
In C kann statischer Speicher mithilfe des static
Schlüsselworts zugewiesen werden . Der Bereich ist nur die Kompilierungseinheit.
Interessanter wird es, wenn das extern
Schlüsselwort berücksichtigt wird . Wenn eine extern
Variable definiert ist, weist der Compiler ihr Speicher zu. Wenn eine extern
Variable deklariert wird , muss der Compiler die Variable an anderer Stelle definieren . Wenn extern
Variablen nicht deklariert / definiert werden, treten Verknüpfungsprobleme auf, während Fehler beim Deklarieren / Definieren von static
Variablen 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 extern
und static
sind zwei getrennte Klassen von Variablen in C.
extern int a; /* Declaration */
int a; /* Definition */
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 data
Abschnitt in der kompilierten Binärdatei erstellen und wenn das Programm in den Speicher geladen wird, die Adresse innerhalb derdata
Das 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.
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 :)
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.
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.
Statische Speicherzuordnung:
Dynamische Speicherzuordnung:
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.
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.
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);