2013-02-12 17 views
5

Sto cercando di capire di più sulla sezione "comune" di un eseguibile e ho notato che quando si esegue uno objdump su un codice compilato, posso vedere le variabili inserite nel codice comune solo sui file oggetto (*.o) non sugli eseguibili.Perché le variabili di sezione comuni vengono visualizzate solo nel file oggetto e non nell'eseguibile?

Perché è quello?

//test.c 

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

comando build:

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

objdump mostra i nella sezione comune nella tabella dei simboli:

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

A meno che non lo faccio funzionare sul file eseguibile:

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

Se ricostruisco il file oggetto con il flag -fno-common, viene invece visualizzato nel segmento .bss proprio come nell'eseguibile. Il file eseguibile finale non ha questa sezione "COMUNE"?

risposta

6

La sezione comune è qualcosa che il linker conosce. In pratica mette tutto il contenuto dello common in una delle tre o quattro sezioni effettive che [un tipico] eseguibile ha (codice o testo, dati, bss - a volte c'è anche un rodata).

Quindi, la variabile finisce in. Bss in questo caso, poiché non sono inizializzate.

Da manuale gcc su -fcommon/-fno-common

Nel codice C, controlla il posizionamento delle variabili globali non inizializzate. I compilatori Unix C hanno tradizionalmente consentito più definizioni di tali variabili in diverse unità di compilazione inserendo le variabili in un blocco comune. Questo è il comportamento specificato da -fcommon ed è il valore predefinito per GCC sulla maggior parte delle destinazioni. D'altra parte, questo comportamento non è richiesto da ISO C, e su alcuni obiettivi può portare una velocità o penalità di dimensione del codice sui riferimenti variabili. L'opzione -fno-common specifica che il compilatore deve posizionare le variabili globali non inizializzate nella sezione dati del file oggetto, anziché generandole come blocchi comuni. Questo ha l'effetto che se la stessa variabile viene dichiarata (senza extern) in due diverse compilazioni, si ottiene un errore di definizione multipla quando si collegano. In questo caso, devi compilare con -fcommon. La compilazione con -fno-common è utile su obiettivi per i quali offre prestazioni migliori oppure se si si desidera verificare che il programma funzioni su altri sistemi che sempre trattino dichiarazioni di variabili non inizializzate in questo modo.

Quindi, -fno-common o -fcommon farà solo una differenza se non v'è più di una variabile globale chiamata i [e dovrebbero essere della stessa dimensione, o il vostro programma non è più valido, che è un grado di peggio di un comportamento indefinito !]

+0

ok ... allora qual è il punto della sezione comune, allora?con sia 'fcommon' che' fno-common' il risultato finale è che le variabili non inizializzate finiscono nel segmento .bss dell'eseguibile; o esiste per la stessa ragione per cui hai scritto '" [a typical] "'? il che significa che ci sono delle eccezioni – Mike

+2

@Mike Ma il compilatore non lo sa - è il lavoro dei linker per capirlo. Con target (e formati eseguibili) che forniscono una sezione .bss, la sezione bss viene normalmente allocata e inizializzata in fase di runtime. Sugli obiettivi che non hanno questa capacità, le sezioni comuni finiscono nell'eseguibile, e se si dispone di un array globale di 10Mb, il tuo eseguibile finisce per essere grande 10Mb. Ciò consente anche di scrivere i propri script di linker e posizionare quelle sezioni comuni dove li si desidera. -fno-comune ha altri usi, che però spiega la pagina man di gcc. – nos

+0

Ho detto "un tipico" perché è possibile aggiungere sezioni aggiuntive in alcune architetture e queste sezioni possono essere assegnate anche a tutti i tipi di attributi. Non tutti i compilatori, i linker, ecc. Lo supporteranno, e 'gcc' è in grado di girare su un gran numero di sistemi, con un gran numero di architetture del sistema operativo. Non volevo che qualcuno facesse notare che su OS glurf, con il linker X, hai sezioni chiamate ..., ecc. –