2013-02-12 4 views
5

Ich versuche, mehr über den "gemeinsamen" Abschnitt einer ausführbaren Datei zu verstehen, und ich bemerkte, dass wenn ich eine objdump auf kompilierten Code, ich sehe Variablen im gemeinsamen Code nur auf Objektdateien (*.o) nicht auf ausführbare Dateien.Warum werden allgemeine Abschnittsvariablen nur in der Objektdatei und nicht in der ausführbaren Datei angezeigt?

Warum ist das?

//test.c 

int i[1000]; 
int main(){return 0;} 

build-Befehl:

> gcc -g0 -fcommon -c test.c 
> gcc -g0 -fcommon test.c 

objdump zeigt i in dem gemeinsamen Abschnitt in der Symboltabelle:

> objdump -x test.o 
    ... 
    SYMBOL TABLE: 
    ... 
    00000fa0 O *COM* 00000020 i 

Wenn ich es auf die ausführbare Datei ausführen:

> objdump -x a.out 
    ... 
    SYMBOL TABLE: 
    ... 
    0804a040 g O .bss 00000fa0 i 

Wenn ich die Objektdatei mit dem -fno-common Flag neu erstellen, wird es im Segment .bss angezeigt, genauso wie es auf der ausführbaren Datei. Verfügt die endgültige ausführbare Datei nicht über diesen Abschnitt "COMMON"?

Antwort

6

Der allgemeine Abschnitt ist etwas, das dem Linker bekannt ist. Es setzt im Grunde alle common Inhalt in einen der drei oder vier tatsächlichen Abschnitte, die [eine typische] ausführbare Datei hat (Code oder Text, Daten, Bss - manchmal gibt es auch eine Rodata).

Ihre Variable endet daher in .bss in diesem Fall, da sie nicht initialisiert sind.

Von gcc Handbuch auf -fcommon/-fno-common

In C-Code steuert die Platzierung von nicht initialisierten globalen Variablen. Unix C Compiler haben traditionell mehrere Definitionen von solchen Variablen in verschiedenen Kompilierungseinheiten erlaubt, indem die Variablen in einem gemeinsamen Block platziert wurden. Dies ist das Verhalten, das von -fcommon angegeben wird. Es ist der Standard für GCC auf den meisten Zielen. Auf der anderen Seite ist dieses Verhalten nicht von ISO C erforderlich, und auf einigen Zielen kann eine Geschwindigkeit oder Codegröße Strafe auf Variablenreferenzen tragen. Die Option -fno-common gibt an, dass der Compiler nicht initialisierte globale Variablen in den Datenabschnitt der Objektdatei platzieren soll, anstatt als allgemeine Blöcke zu generieren. Wenn dieselbe Variable (ohne extern) in zwei verschiedenen Kompilationen deklariert wird, erhalten Sie einen Mehrfachdefinitionsfehler, wenn Sie sie verknüpfen. In diesem Fall müssen Sie mit -fcommon stattdessen kompilieren. Kompilieren mit -fno-common ist nützlich auf Ziele, für die es eine bessere Leistung bietet, oder wenn Sie überprüfen möchten, dass das Programm auf anderen Systemen funktioniert, die immer behandeln nicht initialisierte Variablendeklarationen auf diese Weise.

So -fno-common oder -fcommon nur einen Unterschied machen, wenn es mehr als eine globale Variable namens i [und sie sollen von der gleichen Größe sein, oder Ihr Programm wird ungültig, was eine Klasse schlechter als undefiniertes Verhalten ist !]

+0

ok ... also was ist der Sinn des gemeinsamen Abschnitts dann?Bei "fcommon" und "fno-common" ist das Endergebnis, dass die nicht initialisierten Variablen im .bss-Segment der ausführbaren Datei landen. oder existiert es aus dem gleichen Grund, aus dem du "[ein typisches]" geschrieben hast? Das heißt, es gibt Ausnahmen – Mike

+2

@Mike Aber der Compiler weiß nicht darüber - es ist der Linker-Job, um dies herauszufinden. Bei Zielen (und ausführbaren Formaten), die einen .bss-Abschnitt bereitstellen, wird der bss-Abschnitt normalerweise zur Laufzeit zugewiesen und initialisiert. Auf Zielen, die diese Fähigkeit nicht haben, enden die allgemeinen Abschnitte in der ausführbaren Datei und wenn Sie ein globales Array von 10 MB haben, wird Ihre ausführbare Datei schließlich 10 MB groß. Dies ermöglicht Ihnen auch, Ihre eigenen Linker-Skripte zu schreiben und diese gemeinsamen Bereiche dort zu platzieren, wo Sie sie haben möchten. -fno-common hat andere Verwendungen, was die gcc man-Seite aber erklärt. – nos

+0

Ich sagte "eine typische", weil es möglich ist, zusätzliche Abschnitte in einigen Architekturen hinzuzufügen, und diese Abschnitte können auch alle Arten von Attributen zugeordnet werden. Nicht alle Compiler, Linker usw. unterstützen dies, und "gcc" kann auf einer großen Anzahl von Systemen mit einer großen Anzahl von Betriebssystemarchitekturen ausgeführt werden. Ich wollte nicht, dass jemand darauf hinweist, dass auf OS glurf, mit Linker X, Sektionen mit dem Namen ..., etc. stehen. –

Verwandte Themen