Wo werden statische Variablen in C und C++ gespeichert?

Lesezeit: 10 Minuten

Wo werden statische Variablen in C und C gespeichert
Benoit

In welchem ​​Segment (.BSS, .DATA, andere) einer ausführbaren Datei werden statische Variablen gespeichert, damit sie keine Namenskollision haben? Zum Beispiel:


foo.c:                         bar.c:
static int foo = 1;            static int foo = 10;
void fooTest() {               void barTest() {
  static int bar = 2;            static int bar = 20;
  foo++;                         foo++;
  bar++;                         bar++;
  printf("%d,%d", foo, bar);     printf("%d, %d", foo, bar);
}                              }

Wenn ich beide Dateien kompiliere und sie mit einer Hauptdatei verlinke, die wiederholt fooTest() und barTest aufruft, werden die printf-Anweisungen unabhängig voneinander erhöht. Das ist sinnvoll, da die Variablen foo und bar lokal für die Übersetzungseinheit sind.

Aber wo wird der Speicher zugewiesen?

Um es klar zu sagen, die Annahme ist, dass Sie eine Toolchain haben, die eine Datei im ELF-Format ausgeben würde. Also ich glauben das da hat Platz in der ausführbaren Datei für diese statischen Variablen reserviert werden.
Nehmen wir zu Diskussionszwecken an, dass wir die GCC-Toolchain verwenden.

  • Die meisten Leute sagen Ihnen, dass sie im Abschnitt .DATA gespeichert werden sollten, anstatt Ihre Frage zu beantworten: Wo genau im Abschnitt .DATA und wie finden Sie wo. Ich sehe, Sie haben bereits eine Antwort markiert, also wissen Sie bereits, wie Sie sie finden?

    – Lukmac

    20. März 2011 um 20:50 Uhr


  • warum initialisiert und nicht initialisiert in verschiedenen Abschnitten platziert werden: linuxjournal.com/article/1059

    – mhk

    26. Juli 2012 um 16:39 Uhr

  • Der Speicherplatz, der Ihren globalen/statischen Variablen zur Laufzeit zugewiesen wird, hat nichts mit ihrer Namensauflösung zu tun, die während der Build-/Link-Zeit erfolgt. Nachdem die ausführbare Datei erstellt wurde, gibt es keine Namen mehr.

    – Valdo

    13. Oktober 2014 um 17:50 Uhr


  • Diese Frage ist bedeutungslos, da sie auf der falschen Prämisse basiert, dass “Namenskollision” von nicht exportierten Symbolen eine Sache sein kann, die existieren kann. Die Tatsache, dass es keine legitime Frage gibt, könnte erklären, wie schlimm einige der Antworten sind. Es ist schwer zu glauben, dass so wenige Leute das verstanden haben.

    – Unterstrich_d

    24. Juli 2016 um 22:26 Uhr


1647165619 982 Wo werden statische Variablen in C und C gespeichert
Don Neufeld

Wohin Ihre Statik geht, hängt davon ab, ob sie es sind Null initialisiert. Null initialisiert Statische Daten gehen ein .BSS (Block gestartet durch Symbol), nicht null initialisiert Daten gehen rein .DATEN

  • Mit “Nicht-0 initialisiert” meinen Sie wahrscheinlich “Initialisiert, aber mit etwas anderem als 0”. Weil es in C/C++ keine “nicht initialisierten” statischen Daten gibt. Alles Statische wird standardmäßig mit Null initialisiert.

    – Ant

    19. Juni 2010 um 9:33 Uhr


  • @Don Neufeld: Ihre Antwort beantwortet die Frage überhaupt nicht. Ich verstehe nicht, warum es akzeptiert wird. Weil sowohl ‘foo’ als auch ‘bar’ nicht mit 0 initialisiert sind. Die Frage ist, wo zwei statische/globale Variablen mit demselben Namen in .bss oder .data platziert werden sollen

    – Lukmac

    20. März 2011 um 20:42 Uhr

  • Ich habe Implementierungen verwendet, bei denen explizit nullinitialisierte statische Daten eingegeben wurden .dataund statische Daten ohne Initialisierer gingen ein .bss .

    – MM

    17. August 2014 um 6:22 Uhr


  • @MM In meinem Fall, ob das statische Mitglied nicht initialisiert (implizit auf 0 initialisiert) oder explizit auf 0 initialisiert ist, wird es in beiden Fällen im Abschnitt .bss summiert.

    – Binder

    5. September 2015 um 4:25 Uhr

  • Sind diese Informationen spezifisch für einen bestimmten ausführbaren Dateityp? Ich nehme an, da Sie nicht angegeben haben, dass dies zumindest für ausführbare ELF- und Windows PE-Dateien gilt, aber was ist mit anderen Typen?

    – Jerry Jeremia

    6. April 2020 um 2:57 Uhr

Wo werden statische Variablen in C und C gespeichert
Karn

Wenn ein Programm in den Speicher geladen wird, ist es in verschiedene Segmente organisiert. Eines der Segmente ist DATA-Segment. Das Datensegment ist weiter in zwei Teile unterteilt:

  • Initialisiertes Datensegment: Hier werden alle globalen, statischen und konstanten Daten gespeichert.
  • Nicht initialisiertes Datensegment (BSS): Alle nicht initialisierten Daten werden in diesem Segment gespeichert.

Hier ist ein Diagramm, um dieses Konzept zu erklären:

Geben Sie hier die Bildbeschreibung ein

Hier ist ein sehr guter Link, der diese Konzepte erklärt: Speicherverwaltung in C: Der Heap und der Stack

  • Die obige Antwort besagt, dass 0 initialisiert in BSS geht. Bedeutet 0 initialisiert nicht initialisiert oder 0 per se? Wenn es per se 0 bedeutet, sollten Sie es meiner Meinung nach in Ihre Antwort aufnehmen.

    – Viraj

    22. Oktober 2015 um 2:37 Uhr

  • Konstante Daten werden nicht im .data-Segment, sondern im .const-Segment des Textabschnitts gespeichert.

    – Benutzer10678

    1. November 2017 um 4:34 Uhr

  • Beachten Sie auch, dass “initialisierte Daten” meines Wissens aus initialisiert bestehen können Variablen und Konstanten. Auf einem Mikrocontroller (zB: STM32), Initialisierte Variablen werden standardmäßig in gespeichert Blinken Gedächtnis und beim Start in den Arbeitsspeicher kopiertund initialisierte Konstanten sind darin belassen und sollen gelesen werden, Nur Blitzzusammen mit Textdie das Programm selbst enthält, und wird in belassen Nur Blitz.

    – Gabriel Staples

    5. November 2018 um 21:46 Uhr

  • Link ist kaputt 🙁

    – subtiler Sucher

    28. Februar 2020 um 6:59 Uhr

  • +1 für @GabrielStaples für die Hervorhebung der Tatsache, dass initialisierte Daten weiter in schreibgeschützt (=> .rodata-Abschnitt) und schreibgeschützt (=> .data-Abschnitt) klassifiziert werden können.

    – ZeZNiQ

    27. Januar um 17:57 Uhr

Tatsächlich ist eine Variable ein Tupel (Speicher, Gültigkeitsbereich, Typ, Adresse, Wert):

storage     :   where is it stored, for example data, stack, heap...
scope       :   who can see us, for example global, local...
type        :   what is our type, for example int, int*...
address     :   where are we located
value       :   what is our value

Lokaler Gültigkeitsbereich kann lokal für entweder die Übersetzungseinheit (Quelldatei), die Funktion oder den Block bedeuten, je nachdem, wo sie definiert ist. Um eine Variable für mehr als eine Funktion sichtbar zu machen, muss sie sich definitiv entweder im DATA- oder im BSS-Bereich befinden (je nachdem, ob sie explizit initialisiert wurde oder nicht). Es wird dann entsprechend entweder auf alle Funktionen oder Funktionen in der Quelldatei beschränkt.

  • +1 für gründliche Kategorisierung auf hohem Niveau. Es wäre toll, wenn Sie auch auf die Quelle(n) dieser Informationen hinweisen könnten.

    – ZeZNiQ

    27. Januar um 17:59 Uhr

Der Speicherort der Daten ist implementierungsabhängig.

Allerdings ist die Bedeutung von statisch ist “interne Verknüpfung”. Somit ist das Symbol intern zur Kompilierungseinheit (foo.c, bar.c) und kann nicht außerhalb dieser Kompilierungseinheit referenziert werden. Es kann also keine Namenskollisionen geben.

1647165624 303 Wo werden statische Variablen in C und C gespeichert
ugasoft

im Bereich “global und statisch” 🙂

In C++ gibt es mehrere Speicherbereiche:

  • Haufen
  • kostenlos speichern
  • Stapel
  • global & statisch
  • konst

Sehen Hier für eine ausführliche antwort auf deine frage:

Im Folgenden werden die wichtigsten unterschiedlichen Speicherbereiche eines C++-Programms zusammengefasst. Beachten Sie, dass einige der Namen (z. B. “Haufen”) im Entwurf nicht als solche erscheinen [standard].

     Memory Area     Characteristics and Object Lifetimes
     --------------  ------------------------------------------------

     Const Data      The const data area stores string literals and
                     other data whose values are known at compile
                     time.  No objects of class type can exist in
                     this area.  All data in this area is available
                     during the entire lifetime of the program.

                     Further, all of this data is read-only, and the
                     results of trying to modify it are undefined.
                     This is in part because even the underlying
                     storage format is subject to arbitrary
                     optimization by the implementation.  For
                     example, a particular compiler may store string
                     literals in overlapping objects if it wants to.


     Stack           The stack stores automatic variables. Typically
                     allocation is much faster than for dynamic
                     storage (heap or free store) because a memory
                     allocation involves only pointer increment
                     rather than more complex management.  Objects
                     are constructed immediately after memory is
                     allocated and destroyed immediately before
                     memory is deallocated, so there is no
                     opportunity for programmers to directly
                     manipulate allocated but uninitialized stack
                     space (barring willful tampering using explicit
                     dtors and placement new).


     Free Store      The free store is one of the two dynamic memory
                     areas, allocated/freed by new/delete.  Object
                     lifetime can be less than the time the storage
                     is allocated; that is, free store objects can
                     have memory allocated without being immediately
                     initialized, and can be destroyed without the
                     memory being immediately deallocated.  During
                     the period when the storage is allocated but
                     outside the object's lifetime, the storage may
                     be accessed and manipulated through a void* but
                     none of the proto-object's nonstatic members or
                     member functions may be accessed, have their
                     addresses taken, or be otherwise manipulated.


     Heap            The heap is the other dynamic memory area,
                     allocated/freed by malloc/free and their
                     variants.  Note that while the default global
                     new and delete might be implemented in terms of
                     malloc and free by a particular compiler, the
                     heap is not the same as free store and memory
                     allocated in one area cannot be safely
                     deallocated in the other. Memory allocated from
                     the heap can be used for objects of class type
                     by placement-new construction and explicit
                     destruction.  If so used, the notes about free
                     store object lifetime apply similarly here.


     Global/Static   Global or static variables and objects have
                     their storage allocated at program startup, but
                     may not be initialized until after the program
                     has begun executing.  For instance, a static
                     variable in a function is initialized only the
                     first time program execution passes through its
                     definition.  The order of initialization of
                     global variables across translation units is not
                     defined, and special care is needed to manage
                     dependencies between global objects (including
                     class statics).  As always, uninitialized proto-
                     objects' storage may be accessed and manipulated
                     through a void* but no nonstatic members or
                     member functions may be used or referenced
                     outside the object's actual lifetime.

So finden Sie es selbst mit objdump -Sr

Um wirklich zu verstehen, was vor sich geht, müssen Sie die Linker-Verschiebung verstehen. Wenn Sie das noch nie berührt haben, lesen Sie zuerst diesen Beitrag.

Lassen Sie uns ein Linux x86-64 ELF-Beispiel analysieren, um es selbst zu sehen:

#include <stdio.h>

int f() {
    static int i = 1;
    i++;
    return i;
}

int main() {
    printf("%d\n", f());
    printf("%d\n", f());
    return 0;
}

Kompilieren mit:

gcc -ggdb -c main.c

Code dekompilieren mit:

objdump -Sr main.o
  • -S dekompiliert den Code mit der ursprünglichen Quelle vermischt
  • -r zeigt Umzugsinformationen

Innerhalb der Dekompilierung von f wir sehen:

 static int i = 1;
 i++;
4:  8b 05 00 00 00 00       mov    0x0(%rip),%eax        # a <f+0xa>
        6: R_X86_64_PC32    .data-0x4

und das .data-0x4 sagt, dass es zum ersten Byte des gehen wird .data Segment.

Die -0x4 ist da, weil wir relative RIP-Adressierung verwenden, also die %rip in der Anleitung u R_X86_64_PC32.

Es ist erforderlich, weil RIP auf die zeigt folgende Anweisung, die 4 Bytes danach beginnt 00 00 00 00 was umgesiedelt wird. Ich habe dies näher erklärt unter: https://stackoverflow.com/a/30515926/895245

Wenn wir dann die Quelle ändern, um i = 1 und dieselbe Analyse durchführen, kommen wir zu folgendem Schluss:

  • static int i = 0 geht weiter .bss
  • static int i = 1 geht weiter .data

Ich glaube nicht, dass es zu einer Kollision kommt. Die Verwendung von static auf Dateiebene (außerhalb von Funktionen) markiert die Variable als lokal für die aktuelle Kompilierungseinheit (Datei). Es ist nie außerhalb der aktuellen Datei sichtbar, muss also nie einen Namen haben, der extern verwendet werden kann.

Statik verwenden Innerhalb eine Funktion ist anders – die Variable ist nur für die Funktion sichtbar (ob statisch oder nicht), es ist nur ihr Wert, der über Aufrufe dieser Funktion hinweg beibehalten wird.

Tatsächlich macht Static zwei verschiedene Dinge, je nachdem, wo es sich befindet. Im beide In einigen Fällen ist die Sichtbarkeit der Variablen jedoch so eingeschränkt, dass Sie Namensraumkollisionen beim Verlinken leicht verhindern können.

Allerdings glaube ich, dass es in der gespeichert werden würde DATA Abschnitt, der dazu neigt, Variablen zu haben, die auf andere Werte als Null initialisiert werden. Dies ist natürlich ein Implementierungsdetail, nichts, was der Standard vorschreibt – es kümmert sich nur darum Verhalten, nicht wie die Dinge unter der Decke gemacht werden.

  • @paxdiablo: Sie haben zwei Arten von statischen Variablen erwähnt. Wer von ihnen macht diesen Artikel (en.wikipedia.org/wiki/Data_segment ) beziehen auf? Das Datensegment enthält auch die globalen Variablen (die von Natur aus genau das Gegenteil von statischen sind). So, how does a segment of memory (Data Segment) store variables that can be accessed from everywhere (global variables) and also those which have limited scope (file scope or function scope in case of static variables)?

    – Laser

    18. April 2010 um 13:13 Uhr


  • @eSKay, es hat mit Sichtbarkeit zu tun. In einem Segment können Dinge gespeichert werden, die lokal für eine Kompilationseinheit sind, andere, die vollständig zugänglich sind. Ein Beispiel: Denken Sie an jede Comp-Einheit, die einen Block zum DATA-Segment beiträgt. Es weiß wo alles ist in diesem Block. Es veröffentlicht auch die Adressen jener Dinge in dem Block, zu denen es wünscht, dass andere Comp-Einheiten Zugriff darauf haben. Der Linker kann diese Adressen zur Linkzeit auflösen.

    – paxdiablo

    18. April 2010 um 14:29 Uhr

997070cookie-checkWo werden statische Variablen in C und C++ gespeichert?

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

Privacy policy