web-dev-qa-db-de.com

Wo im Speicher sind meine Variablen in C gespeichert?

Wenn man bedenkt, dass der Speicher in vier Segmente unterteilt ist: Daten, Heap, Stapel und Code, wobei globale Variablen, statische Variablen, konstante Datentypen, lokale Variablen (definiert und deklariert in Funktionen), Variablen (in Hauptfunktion), Zeiger , und dynamisch zugewiesenen Speicherplatz (mit Malloc und Calloc) im Speicher gespeichert werden?

Ich denke, sie würden wie folgt vergeben:

  • Globale Variablen -------> Daten
  • Statische Variablen -------> Daten
  • Konstante Datentypen -----> Code
  • Lokale Variablen (in Funktionen deklariert und definiert) --------> stack
  • In der Hauptfunktion deklarierte und definierte Variablen -----> Heap
  • Zeiger (zum Beispiel char *arr, int *arr) -------> Haufen
  • Dynamisch zugewiesener Speicherplatz (mithilfe von malloc und calloc) --------> stack

Ich beziehe mich auf diese Variablen nur aus der C-Perspektive.

Bitte korrigieren Sie mich, wenn ich falsch liege, da ich neu bei C bin.

127
starkk92

Sie haben einige davon richtig verstanden, aber wer auch immer die Fragen schrieb, hat Sie auf mindestens eine Frage gebracht:

  • globale Variablen -------> Daten (korrekt)
  • statische Variablen -------> Daten (korrekt)
  • konstante Datentypen -----> Code und/oder Daten. Betrachten Sie Zeichenfolgenliterale für eine Situation, in der eine Konstante selbst im Datensegment gespeichert und Verweise darauf in den Code eingebettet werden
  • lokale Variablen (deklariert und definiert in Funktionen) --------> Stack (korrekt)
  • variablen, die in der main -Funktion -----> deklariert und definiert wurden haufen auch Stack (der Lehrer hat versucht, dich auszutricksen)
  • zeiger (zB: char *arr, int *arr) -------> haufen Daten oder Stapel, je nach Kontext. Mit C können Sie einen globalen oder einen static -Zeiger deklarieren. In diesem Fall würde der Zeiger selbst im Datensegment enden.
  • dynamisch zugewiesener Speicherplatz (mit malloc, calloc, realloc) --------> stapel Haufen

Erwähnenswert ist, dass "Stapel" offiziell als "automatische Speicherklasse" bezeichnet wird.

183
dasblinkenlight

Für diejenigen zukünftigen Besucher, die sich vielleicht für diese Speichersegmente interessieren, schreibe ich wichtige Punkte zu 5 Speichersegmenten in C:

Einige Köpfe nach oben:

  1. Jedes Mal, wenn ein C-Programm ausgeführt wird, wird im RAM) ein Speicher für die Programmausführung reserviert. Dieser Speicher wird zum Speichern des häufig ausgeführten Codes (Binärdaten), der Programmvariablen usw. verwendet. Der folgende Speicher Segmente spricht über das gleiche:
  2. Normalerweise gibt es drei Arten von Variablen:
    • Lokale Variablen (in C auch als automatische Variablen bezeichnet)
    • Globale Variablen
    • Statische Variablen
    • Sie können globale statische oder lokale statische Variablen haben, aber die obigen drei sind die übergeordneten Typen.

5 Speichersegmente in C:

1. Codesegment

  • Das Codesegment, auch als Textsegment bezeichnet, ist der Speicherbereich, der den häufig ausgeführten Code enthält.
  • Das Codesegment ist häufig schreibgeschützt, um das Risiko zu vermeiden, durch Programmierfehler wie Pufferüberlauf usw. überschrieben zu werden.
  • Das Codesegment enthält keine Programmvariablen wie lokale Variablen ( in C auch als automatische Variablen bezeichnet), globale Variablen usw.
  • Basierend auf der C-Implementierung kann das Codesegment auch schreibgeschützte Zeichenfolgenliterale enthalten. Wenn Sie beispielsweise printf("Hello, world") ausführen, wird im Code-/Textsegment die Zeichenfolge "Hello, world" erstellt. Sie können dies mit dem Befehl size unter Linux überprüfen.
  • Weiterführende Literatur

Datensegment

Das Datensegment ist in die folgenden zwei Teile unterteilt und liegt normalerweise unterhalb des Heap-Bereichs oder in einigen Implementierungen oberhalb des Stapels, das Datensegment liegt jedoch niemals zwischen dem Heap- und dem Stack-Bereich.

2. Nicht initialisiertes Datensegment

  • Dieses Segment wird auch als bss bezeichnet.
  • Dies ist der Teil des Gedächtnisses, der enthält:
    1. Nicht initialisierte globale Variablen (einschließlich Zeigervariablen)
    2. Nicht initialisierte konstante globale Variablen .
    3. Nicht initialisierte lokale statische Variablen .
  • Alle globalen oder statischen lokalen Variablen, die nicht initialisiert sind, werden im nicht initialisierten Datensegment gespeichert
  • Beispiel: Die globale Variable int globalVar; Oder die statische lokale Variable static int localStatic; Werden im nicht initialisierten Datensegment gespeichert.
  • Wenn Sie eine globale Variable deklarieren und als 0 Oder NULL initialisieren, wird sie weiterhin in ein nicht initialisiertes Datensegment oder bss verschoben.
  • Weiterführende Literatur

3. Initialisiertes Datensegment

  • In diesem Segment werden gespeichert:
    1. Initialisierte globale Variablen (einschließlich Zeigervariablen)
    2. Initialisierte konstante globale Variablen .
    3. Initialisierte lokale statische Variablen .
  • Beispiel: Die globale Variable int globalVar = 1; Oder die statische lokale Variable static int localStatic = 1; Werden im initialisierten Datensegment gespeichert.
  • Dieses Segment kann weiter in einen initialisierten Nur-Lese-Bereich und einen initialisierten Lese-Schreib-Bereich unterteilt werden. Initialisierte konstante globale Variablen werden in den initialisierten Nur-Lese-Bereich verschoben, während Variablen, deren Werte zur Laufzeit geändert werden können, in den initialisierten Schreib-Lese-Bereich verschoben werden.
  • Die Größe dieses Segments wird durch die Größe der Werte im Quellcode des Programms bestimmt und ändert sich zur Laufzeit nicht.
  • Weiterführende Literatur

4. Stapelsegment

  • Das Stapelsegment wird zum Speichern von Variablen verwendet, die in Funktionen erstellt wurden ( Funktion kann Hauptfunktion oder benutzerdefinierte Funktion sein), Variable wie
    1. Lokale Variablen der Funktion (einschließlich Zeigervariablen)
    2. An function übergebene Argumente
    3. Absenderadresse
  • Im Stapel gespeicherte Variablen werden entfernt, sobald die Funktionsausführung abgeschlossen ist.
  • Weiterführende Literatur

5. Heap-Segment

  • Dieses Segment soll die dynamische Speicherzuweisung unterstützen. Wenn der Programmierer etwas Speicher dynamisch zuweisen möchte, erfolgt dies in C mit den Methoden malloc, calloc oder realloc.
  • Wenn beispielsweise int* prt = malloc(sizeof(int) * 2), werden acht Bytes im Heap zugewiesen und die Speicheradresse dieses Speicherorts wird zurückgegeben und in der Variablen ptr gespeichert. Die Variable ptr befindet sich je nach Deklaration/Verwendung entweder im Stack oder im Datensegment.
  • Weiterführende Literatur
102
hagrawal

Korrigiert deine falschen Sätze

constant data types ----->  code //wrong

lokale konstante Variablen -----> Stack

initialisierte globale konstante Variable -----> Datensegment

nicht initialisierte globale konstante Variable -----> bss

variables declared and defined in main function  ----->  heap //wrong

variablen, die in der Hauptfunktion -----> stack deklariert und definiert wurden

pointers(ex:char *arr,int *arr) ------->  heap //wrong

dynamically allocated space(using malloc,calloc) --------> stack //wrong

zeiger (zB char * arr, int * arr) -------> Größe dieser Zeigervariable wird im Stapel sein.

Bedenken Sie, dass Sie den Speicher von n Bytes (mit malloc oder calloc) dynamisch zuweisen und dann den Zeiger variabel machen, um darauf zu verweisen. Nun, da sich n Bytes des Speichers im Heap befinden und die Zeigervariable 4 Bytes (wenn 64-Bit-Maschine 8 Bytes) benötigt, die im Stack sein werden, um den Startzeiger des n Bytes des Speichers zu speichern Stück.

Hinweis: Zeigervariablen können auf den Speicher eines beliebigen Segments verweisen.

int x = 10;
void func()
{
int a = 0;
int *p = &a: //Now its pointing the memory of stack
int *p2 = &x; //Now its pointing the memory of data segment
chat *name = "ashok" //Now its pointing the constant string literal 
                     //which is actually present in text segment.
char *name2 = malloc(10); //Now its pointing memory in heap
...
}

dynamisch zugewiesener Speicherplatz (mithilfe von malloc, calloc) --------> Heap

8
rashok

Eine beliebte Desktop-Architektur unterteilt den virtuellen Speicher eines Prozesses in mehrere Segmente:

  • Textsegment: Enthält den ausführbaren Code. Der Befehlszeiger nimmt Werte in diesem Bereich an.

  • Datensegment: Enthält globale Variablen (d. H. Objekte mit statischer Verknüpfung). Unterteilt in schreibgeschützte Daten (z. B. Zeichenfolgenkonstanten) und nicht initialisierte Daten ("BSS").

  • Stapelsegment: Enthält den dynamischen Speicher für das Programm, d. H. Den freien Speicher ("Heap") und die lokalen Stapelrahmen für alle Threads. Traditionell sind der C-Stapel und der C-Haufen von entgegengesetzten Enden in das Stapelsegment hineingewachsen, aber ich glaube, dass die Praxis aufgegeben wurde, weil sie zu unsicher ist.

Ein C-Programm fügt normalerweise Objekte mit statischer Speicherdauer in das Datensegment ein, dynamisch zugewiesene Objekte im freien Speicher und automatische Objekte im Aufrufstapel des Threads, in dem es sich befindet.

Auf anderen Plattformen, wie dem alten x86-Real-Modus oder auf eingebetteten Geräten, können sich die Dinge offensichtlich grundlegend ändern.

6
Kerrek SB

Ich beziehe mich nur aus der C-Perspektive auf diese Variablen.

Aus der Perspektive von C-Sprache kommt es nur auf Umfang, Umfang, Verknüpfung und Zugang an; Die genaue Zuordnung von Elementen zu verschiedenen Speichersegmenten hängt von der jeweiligen Implementierung ab. Dies kann variieren. Der Sprachstandard spricht nicht über Speichersegmente überhaupt. Die meisten modernen Architekturen verhalten sich meist genauso. Blockbereichsvariablen und Funktionsargumente werden aus dem Stapel zugewiesen, Dateibereichs- und statische Variablen werden aus einem Daten- oder Codesegment zugewiesen, dynamischer Speicher wird aus einem Heap zugewiesen, einige konstante Daten werden in Nur-Lese-Segmenten gespeichert , usw.

5
John Bode
  • Variablen/automatische Variablen ---> Stapelabschnitt
  • Dynamisch zugewiesene Variablen ---> Heap-Abschnitt
  • Initialisierte globale Variablen -> Datenabschnitt
  • Nicht initialisierte globale Variablen -> Datenabschnitt (bss)
  • Statische Variablen -> Datenbereich
  • String-Konstanten -> Textabschnitt/Codeabschnitt
  • Funktionen -> Textabschnitt/Codeabschnitt
  • Textcode -> Textabschnitt/Codeabschnitt
  • Register -> CPU-Register
  • Kommandozeilen-Eingaben -> Umgebung/Kommandozeilen-Bereich
  • Umgebungsvariablen -> Umgebung/Befehlszeilenabschnitt
1
prashad

zeiger (zB char * arr, int * arr) -------> heap

Nein, sie können sich auf dem Stack oder im Datensegment befinden. Sie können überall zeigen.

1
Steve Wellens

Eine Sache, die man bei der Speicherung beachten muss, ist die als ob Regel . Der Compiler muss eine Variable nicht an einer bestimmten Stelle ablegen, sondern kann sie an einer beliebigen Stelle ablegen, solange sich das kompilierte Programm wie folgt verhält : Es war ein Programm, das in der abstrakten C-Maschine gemäß ihren Regeln ausgeführt wurde. Dies gilt für alle Speicherdauern . Zum Beispiel:

  • eine Variable, auf die nicht auf alle zugegriffen wird, kann vollständig entfernt werden - sie hat keinen Speicher ... irgendwo. Beispiel - Sehen Sie, wie sich 42 Im generierten Assembly-Code befindet, aber kein Zeichen von 404.
  • eine Variable mit automatischer Speicherdauer, deren Adresse nicht vergeben ist, muss überhaupt nicht gespeichert werden. Ein Beispiel wäre eine Schleifenvariable.
  • eine Variable, die const oder effektiv const ist, muss sich nicht im Speicher befinden. Beispiel - Der Compiler kann beweisen, dass foo effektiv const ist, und seine Verwendung in den Code einfügen. bar hat eine externe Verknüpfung und der Compiler kann nicht beweisen, dass es nicht außerhalb des aktuellen Moduls geändert werden würde, daher ist es nicht inline.
  • ein mit malloc zugewiesenes Objekt muss sich nicht im von heap zugewiesenen Speicher befinden! Beispiel - Beachten Sie, dass der Code keinen Aufruf von malloc hat und der Wert 42 auch nie gespeichert wird. Er wird in einem Register gespeichert!
  • somit muss ein Objekt, das von malloc zugewiesen wurde und dessen Referenz verloren geht, ohne dass die Zuordnung des Objekts zu free aufgehoben wurde, nicht Speicher lecken ...
  • das von malloc zugewiesene Objekt muss sich nicht im Heap unterhalb der Programmunterbrechung (sbrk(0)) unter Unixen befinden. ..
0
Antti Haapala