Frage

Ich bin sehr neugierig auf den Stapelspeicher-Organisation, nachdem ich experimentieren, was im Hintergrund vor sich geht und offensichtlich sah es mit winzigen Wissen zusammenbringt ich aus Bücher erworben. Ich wollte nur überprüfen, ob ich richtig verstanden, was ich ist.

Ich habe ein grundlegendes Programm - hat zwei Funktionen, erste ist foo und der andere ist main (der Einstiegspunkt).

void foo(){
    // do something here or dont
}

int main(){

    int i = 0;

    printf("%p %p %p\n",foo, &i, main);

    system("PAUSE");
    return EXIT_SUCCESS;
};

Die Ausgabe des Programms ist unten, lokalen Variable Main gezeigt i total in einer unabhängigen Position befindet. integer ist ein Werttyp, sondern überprüft es wieder mit einem char * Zeiger lokal für Haupt- und erhalten ähnliche Ergebnisse.

00401390 0022FF44 00401396
Press any key to continue . . .

Ich verstehe, in erster Linie, dass Code und Variablen sind in verschiedene Segmente des Speichers (Codesegment / Datensegment) zugeordnet. Also im Grunde ist es richtig zu sagen, Call-Stack kollabiert grundlegende Informationen über die Ausführung von Funktionen (den lokalen Variablen, Parametern, Rückkehr Punkten) und hält sie im Datensegment?

War es hilfreich?

Lösung

Ein kleiner Nachteil am Anfang: alle diese Antworten sind etwas beeinträchtigt durch das Betriebssystem und Hardware-Architektur. Windows tut Dinge ziemlich radikal anders als UNIX-ähnliche Sprachen, Echtzeit-Betriebssysteme und altes Kleinsystem UNIX.

Aber die grundlegende Antwort als @Richie und @ Paul gesagt hat, ist „Ja“. Wenn Ihr Compiler und Linker mit dem Code durchkommen, wird es aufgebrochen in dem, was als „Text“ ist bekannt und „Daten“ Segmente in UNIX. A Textsegment enthält Anweisungen und einige Arten von statischen Daten; ein Datensegment enthält, und die Daten.

A großen Teil des Datensegments wird dann für die Stapel und Heap-Speicher zugeordnet. Andere Stücke können, um Dinge wie statische oder extern Datenstrukturen zugeordnet werden.

Also ja, wenn das Programm läuft, wird der Programmzähler eifrig Anweisungen von einem anderen Segment als die Daten abgerufen werden. Jetzt sind wir in einigen Architektur Abhängigkeiten, aber in der Regel, wenn Sie haben segmentierte Speicher Ihre Anweisungen so ausgebildet sind, dass ein Byte aus den Segmenten holen so effizient wie möglich ist, in der alten 360-Architektur, hatten sie Basisregister , haben in x86 ein Bündel von Haaren, die als der Adressraum wuchs zu den alten 8080 die auf modernen Prozessoren ging, aber alle Anweisungen sind sehr sorgfältig optimiert, weil, wie Sie sich vorstellen können, Abrufen von Befehlen und ihre Operanden sind sehr intensiv genutzt.

Jetzt sind wir et auf modernere Architekturen mit virtuellem Speicher und Speicherverwaltungseinheit s. Nun hat die Maschine spezifische Hardware, die das Programm Lassen Sie uns den Adressraum als eine große Wohnung Bereich von Adressen behandeln; einfach die verschiedenen Segmente in diesem Bit virtuellen Adressraum erhalten platziert. Die Aufgabe des MMU ist eine virtuelle Adresse zu nehmen und es in eine physische Adresse zu übersetzen, einschließlich dessen, was, wenn die virtuelle Adresse im Moment überhaupt im physischen Speicher sein, geschieht nicht zu tun. Auch hier ist die MMU-Hardware sehr stark optimiert, aber das bedeutet nicht, es ist nicht Leistungskosten verbunden. Aber wie Prozessoren schneller bekommen haben und Programme haben goten größer, es wird immer weniger wichtig.

Andere Tipps

Ja, das ist genau richtig. Code und Daten leben in verschiedenen Teilen des Speichers, mit unterschiedlichen Berechtigungen. Der Stapel hält Parameter, Absenderadressen und lokale ( „automatisch“) Variablen und lebt mit den Daten.

Ja.

Stellen Sie sich vor, dass Ihr Codespeicher ROM ist, und Ihre Datenspeicher RAM (eine gemeinsame kleine Chip-Architektur). Dann sehen Sie den Stapel muss in Datenspeicher sein.

Nun, ich kann für SPARC sprechen:

Ja. Wenn Sie das Programm ausführen, wird das Programm zweimal gelesen (zumindest in SPARC). Das Programm wird in den Speicher geladen und alle Array / Stapelzuordnungen danach erhalten geladen. Im zweiten Durchgang durch das Programm, bekommen die Stapel in einzelne Speicher zugewiesen.

Ich bin nicht sicher für CISC-basierten Prozessoren, aber ich vermute, dass es nicht zu viel variieren.

Ihr Programm zeigt nicht definiertes Verhalten speziell, weil:

  • Sie scheitern <stdio.h> oder <cstdio> enthalten abhängig von der Sprache Sie Ihren Code kompilieren wie
  • printf und alle variablen Argumente Funktionen haben nicht die Fähigkeit, ihre Argumente zu geben zu überprüfen. Daher ist es zwingend auf Ihrer Seite korrekt eingegeben Argumente zu übergeben. Sie sollten wirklich tun:
  • system() hat keine Erklärung in ihrem Umfang. Fügen Sie <stdlib.h> oder <cstdlib> wie der Fall vielleicht.

Schreiben Sie Ihren Code wie:

   #include <stdio.h>

   int main() {
      /* ... */
      printf("%p %p %p\n", (void *)foo, (void *)&i, (void *)main);
      /* ... */
   }

Beachten Sie auch, dass:

  • Die Definition von void foo() ist kein Prototyp in C, aber in C ++. Wenn Sie jedoch schreiben sind void foo(void) Sie einen Prototyp in beiden Sprachen erhalten würde.
  • system() ist abhängig von der Implementierung - Code verhält sich möglicherweise nicht wie erwartet auf allen Plattformen
  • .

Die Sprache selbst (C oder C ++) stellt keine Einschränkungen, wie Speicher zu organisieren. Es hat noch nicht einmal das Konzept eines Stapels oder einen Haufen. Diese werden durch Implementierungen definiert als sie es für richtig halten. Sie sollten idealerweise Dokumentation durch die Implementierung zur Verfügung gestellt konsultieren eine Vorstellung davon zu bekommen, was sie tun.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top