Come accennato da dasblinken, GCC 4.8 mette le statistiche locali sullo stesso posto dei globali.
Più precisamente:
static int i = 0
va avanti .bss
static int i = 1
va avanti .data
Analizziamo esempio ELF uno Linux x86-64 per vedere noi stessi:
#include <stdio.h>
int f() {
static int i = 1;
i++;
return i;
}
int main() {
printf("%d\n", f());
printf("%d\n", f());
return 0;
}
Per raggiungere conclusioni, dobbiamo capire le informazioni sulla ricollocazione. Se non l'hai mai toccato, considera reading this post first.
Compilarlo:
gcc -ggdb -c main.c
decompilare il codice con:
objdump -S main.o
f
contiene:
int f() {
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
static int i = 1;
i++;
4: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a <f+0xa>
a: 83 c0 01 add $0x1,%eax
d: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 13 <f+0x13>
return i;
13: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 19 <f+0x19>
}
19: 5d pop %rbp
1a: c3 retq
che fa 3 accessi al i
:
4
sposta nella eax
per preparare l'incremento
d
sposta il valore incrementato alla memoria
13
sposta i
al eax
per il valore restituito. Ovviamente non è necessario poiché lo contiene già eax
e -O3
è in grado di rimuoverlo.
Quindi cerchiamo di concentrarsi solo sulla 4
:
4: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a <f+0xa>
Guardiamo i dati trasferimento:
readelf -r main.o
che dice come gli indirizzi sezione di testo saranno modificati dal linker quando è rendendo l'eseguibile.
Contiene:
Relocation section '.rela.text' at offset 0x660 contains 9 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000006 000300000002 R_X86_64_PC32 0000000000000000 .data - 4
guardiamo .rela.text
e non gli altri perché siamo interessati a delocalizzazioni di .text
.
Offset 6
cade a destra nella istruzione che inizia nel byte 4:
4: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a <f+0xa>
^^
This is offset 6
Dalla nostra conoscenza di codifica x86-64 istruzione:
8b 05
è la parte mov
00 00 00 00
è il indirizzo parte, che inizia al byte 6
AMD64 System V ABI Update ci dice che R_X86_64_PC32
agisce su 4 byte (00 00 00 00
) e calcola l'indirizzo:
S + A - P
che significa:
S
: il segmento sottolineato: .data
A
: il Added
: -4
P
: l'indirizzo del byte 6 quando caricato
-P
è necessaria perché GCC utilizzato RIP
indirizzamento relativo, quindi dobbiamo scontare la posizione in .text
-4
è necessario perché RIP
punti al seguente istruzione a byte 0xA
ma P
è il byte 0x6
, quindi è necessario lo sconto 4.
Conclusione: dopo il collegamento verrà indicato il primo byte del segmento .data
.
Perché pensi che il nome che il compilatore utilizza a livello di linker è lo stesso nome che dichiari? – bmargulies
possibile duplicato di questo: [cosa “statica” significa in un programma C] [1] [1]: http: // StackOverflow.it/questions/572547/what-does-static-mean-in-ac-program – tejas
possibile duplicato di [Dove sono memorizzate le variabili statiche (in C/C++)?] (http://stackoverflow.com/questions/93039/ dove-sono-static-variabili-memorizzate-in-cc) – jogojapan