Si consideri il seguente codice sorgente C++:Utilizzando simbolo '_end' in g ++ porta ad un errore di segmentazione
int _end[1050];
int main() {
for (int i = 0; i < 1050; i++)
_end[i] = 0;
return 0;
}
linea di compilazione: g++ main.cpp -o main -O0
L'esecuzione di questo codice porta a errore di segmentazione quando si utilizza gcc-4.8. 4 e clang-3.6.0 sotto Ubuntu 14.04. Lo strano comportamento è che il simbolo _end
punti alla fine di un array assegnato staticamente _end
, non all'inizio. Se sostituiamo _end
con end_
, tutto funziona correttamente.
Inoltre, se chiediamo gcc ad emettere un codice assembly fornendo -S argomento della riga di comando, non vi sarà alcuna differenza significativa tra la versione con "_end" e la versione con qualsiasi altro nome di matrice:
$ g++ main.cpp -o main.s -O0 -S
$ g++ main2.cpp -o main2.s -O0 -S
$ diff main.s main2.s
1,2c1,2
< .file "main.cpp"
< .globl _end
---
> .file "main2.cpp"
> .globl end_
5,7c5,7
< .type _end, @object
< .size _end, 4200
< _end:
---
> .type end_, @object
> .size end_, 4200
> end_:
25c25
< movl $0, _end(,%rax,4)
---
> movl $0, end_(,%rax,4)
Ma se usiamo objdump eseguire il dump dei file eseguibili ed eseguire diff contro di loro, vedremo che nel _end
versione l'indirizzo utilizzato è 4200 = 4 * 1050 byte oltre che necessaria:
$ g++ main.cpp -o main -O0
$ g++ main2.cpp -o main2 -O0
$ objdump -d main >main.dump
$ objdump -d main2 > main2.dump
$ diff main.dump main2.dump
2c2
< main: формат файла elf64-x86-64 // "File format" in Russian
---
> main2: формат файла elf64-x86-64
123c123
< 4004ff: c7 04 85 c8 20 60 00 movl $0x0,0x6020c8(,%rax,4)
---
> 4004ff: c7 04 85 60 10 60 00 movl $0x0,0x601060(,%rax,4)
per quanto riguarda Lo so, il compilatore gcc può trattare il variab iniziando con underscore come vuole, i. e. questa è una cattiva pratica per usare tali simboli nel codice. Ma la mia domanda è: cosa succede veramente qui? Perché _end
viene sostituito con un indirizzo di fine di un array assegnato? Perché non c'è differenza se usiamo l'argomento della riga di comando "-S", ma esiste effettivamente una differenza nei binari creati? Non che gcc e clang si comportino in modo identico in questo caso, anche per me è strano.
Esattamente quello di cui avevo bisogno, grazie! Ma perché l'argomento della riga di comando "-S" non mostra nulla di sospetto durante la compilazione di questo codice? –
@MaximAkhmedov Questo probabilmente è dovuto al fatto che '_end' è un puntatore come qualsiasi altro puntatore e l'aritmetica del puntatore viene eseguita quando si assegna all'array. – vsoftco