Wo werden String-Konstanten von GCC gespeichert und woher kommen diese Zeiger?

8

Wenn ich folgendes C-Programm auf meinem Linux x86_64-Rechner kompiliere und ausführe, kompiliert von GCC:

%Vor%

Ich bekomme immer die Ausgabe als:

  

gleich 0x40064c 0x40064c

Ich verstehe, dass Strings in einer konstanten Tabelle gespeichert sind, aber die Adresse im Vergleich zu dynamisch zugewiesenem Speicher zu niedrig ist.

Vergleiche mit folgendem Programm:

%Vor%

Die beiden Zeiger sind nicht gleich, da dies zwei Arrays sind, die unabhängig voneinander manipuliert werden können.

Ich möchte wissen, wie GCC den Code für diese beiden Programme generiert und wie sie während der Ausführung dem Speicher zugeordnet werden. Da dies bereits dokumentiert wäre, sind viele Links zur Dokumentation ebenfalls willkommen.

    
Xolve 12.09.2012, 18:03
quelle

1 Antwort

11
___ tag123linux ___ LINUX FRAGEN MÜSSEN PROGRAMMIEREN VERWANDT SEIN. Verwenden Sie dieses Tag nur dann, wenn sich Ihre Frage auf das Programmieren mit Linux-APIs oder das Linux-spezifische Verhalten bezieht, nicht nur, weil Sie Ihren Code unter Linux ausführen. Wenn Sie Linux-Unterstützung benötigen, können Sie https://unix.stackexchange.com oder https://askubuntu.com ausprobieren ___ tag123string ___ Eine Zeichenfolge ist eine endliche Abfolge von Symbolen, die üblicherweise für Text verwendet wird, manchmal jedoch auch für beliebige Daten. ___ tag123gcc ___ GCC ist die GNU Compiler-Sammlung. Es ist der De-facto-Standard-C-Compiler unter Linux und unterstützt auch viele andere Sprachen und Plattformen. ___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt. ___ tag123compilerconstruction ___ Das Tag compiler-construction sollte auf Fragen zur Programmierung von Compilern oder auf Fragen zu den inneren Details von Compilern angewendet werden. NUTZEN SIE NICHT für Fragen zum * Verwenden * spezifischer Compiler oder Kompilierungsfehler. ___ qstnhdr ___ Wo werden String-Konstanten von GCC gespeichert und woher kommen diese Zeiger? ___ qstntxt ___

Wenn ich folgendes C-Programm auf meinem Linux x86_64-Rechner kompiliere und ausführe, kompiliert von GCC:

%Vor%

Ich bekomme immer die Ausgabe als:

  

gleich 0x40064c 0x40064c

Ich verstehe, dass Strings in einer konstanten Tabelle gespeichert sind, aber die Adresse im Vergleich zu dynamisch zugewiesenem Speicher zu niedrig ist.

Vergleiche mit folgendem Programm:

%Vor%

Die beiden Zeiger sind nicht gleich, da dies zwei Arrays sind, die unabhängig voneinander manipuliert werden können.

Ich möchte wissen, wie GCC den Code für diese beiden Programme generiert und wie sie während der Ausführung dem Speicher zugeordnet werden. Da dies bereits dokumentiert wäre, sind viele Links zur Dokumentation ebenfalls willkommen.

    
___ antwort12394056 ___

In beiden Fällen gibt der Compiler die eigentlichen Bytes der Zeichenfolge "hello" nur einmal im Abschnitt .rodata des Programms aus ( rodata steht für schreibgeschützte Daten ).

Sie werden tatsächlich direkt aus der ausführbaren Datei in den Speicher gemappt, ähnlich wie der Codeabschnitt. Deshalb sind sie weit von den dynamisch zugewiesenen entfernt.

Dann:

%Vor%

Initialisiert einfach p auf die Adresse dieser (schreibgeschützten) Daten. Und offensichtlich:

%Vor%

Ruft die gleiche Adresse ab. Dies wird string pooling genannt und ist eine optionale populäre Optimierung des Compilers.

Aber wenn du schreibst:

%Vor%

Es wird wahrscheinlich so etwas erzeugen:

%Vor%

Als "hello" ist eigentlich die Adresse der schreibgeschützten Pool-Zeichenkette.

Der Aufruf von memcpy dient nur zu Illustrationszwecken. Es kann sehr gut sein, inline zu kopieren, anstatt mit einem Funktionsaufruf.

Wenn Sie später tun:

%Vor%

Es wird ein anderes Array und ein anderes memcpy() definieren. Also gleiche Daten, aber unterschiedliche Adressen.

Aber wo werden diese Array-Variablen liegen? Nun, das kommt drauf an.

  • Wenn sie lokal sind, nicht statisch, Variablen: im Stapel.
  • Wenn es sich um globale Variablen handelt, dann befinden sie sich im Abschnitt .data der ausführbaren Datei und werden dort mit den richtigen Zeichen gespeichert, so dass in der Laufzeit kein memcpy benötigt wird. Das ist nett, denn das memcpy müsste vor main ausgeführt werden.
  • Wenn es sich um lokale statische Variablen handelt: genau so wie bei globalen Variablen. Beide zusammen heißen variables of static duration oder so ähnlich.

Über die Links zur Dokumentation, tut mir leid, ich kenne keine.

Aber wer braucht Dokumentation, wenn Sie selbst experimentieren können? Dafür ist das beste Werkzeug um objdump , es kann das Programm zerlegen, die Datenabschnitte ablegen und vieles mehr!

Ich hoffe, dies beantwortet Ihre Fragen ...

    
___
rodrigo 12.09.2012, 18:15
quelle