Em que segmento (.BSS, .DATA, outro) de um arquivo executável são variáveis estáticas armazenadas para que não tenham colisão de nomes? Por exemplo:
foo.c: bar.c:
static int foo = 1; static int foo = 10;
void fooTest() { void barTest() {
static int bar = 2; static int bar = 20;
foo++; foo++;
bar++; bar++;
printf("%d,%d", foo, bar); printf("%d, %d", foo, bar);
} }
Se eu compilar os dois arquivos e o vincular a um main que chama fooTest () e barTest repetidamente, as instruções printf aumentam independentemente. Faz sentido, pois as variáveis foo e bar são locais na unidade de tradução.
Mas onde o armazenamento é alocado?
Para deixar claro, a suposição é que você possui uma cadeia de ferramentas que produziria um arquivo no formato ELF. Portanto, acredito que deve haver algum espaço reservado no arquivo executável para essas variáveis estáticas.
Para fins de discussão, vamos supor que usamos a cadeia de ferramentas do GCC.
c++
c
compiler-construction
Benoit
fonte
fonte
Respostas:
Para onde suas estatísticas vão depende se elas são inicializadas com zero . dados estáticos inicializados com zero entram em .BSS (bloco iniciado por símbolo) , dados não inicializados com zero entram em .DATA
fonte
.data
e dados estáticos sem inicializador.bss
.Quando um programa é carregado na memória, ele é organizado em diferentes segmentos. Um dos segmentos é o segmento DATA . O segmento de dados é subdividido em duas partes:
segmento de dados inicializado: todos os dados globais, estáticos e constantes são armazenados aqui.
Segmento de dados não inicializados (BSS): todos os dados não inicializados são armazenados neste segmento.
Aqui está um diagrama para explicar esse conceito:
aqui está um link muito bom explicando esses conceitos:
fonte
De fato, uma variável é tupla (armazenamento, escopo, tipo, endereço, valor):
Escopo local pode significar local para a unidade de tradução (arquivo de origem), a função ou o bloco, dependendo de onde está definido. Para tornar a variável visível para mais de uma função, ela definitivamente precisa estar na área DATA ou BSS (dependendo se foi inicializada explicitamente ou não, respectivamente). Seu escopo é definido de acordo com todas as funções ou funções no arquivo de origem.
fonte
O local de armazenamento dos dados dependerá da implementação.
No entanto, o significado de estático é "ligação interna". Portanto, o símbolo é interno à unidade de compilação (foo.c, bar.c) e não pode ser referenciado fora dessa unidade de compilação. Portanto, não pode haver colisões de nomes.
fonte
na área "global e estática" :)
Existem várias áreas de memória no C ++:
Veja aqui uma resposta detalhada à sua pergunta:
fonte
Eu não acredito que haverá uma colisão. O uso de estática no nível do arquivo (funções externas) marca a variável como local para a unidade de compilação atual (arquivo). Ele nunca é visível fora do arquivo atual, portanto, nunca precisa ter um nome que possa ser usado externamente.
O uso de estática dentro de uma função é diferente - a variável é visível apenas para a função (estática ou não), mas seu valor é preservado nas chamadas para essa função.
Com efeito, a estática faz duas coisas diferentes, dependendo de onde está. Nos dois casos, no entanto, a visibilidade da variável é limitada de forma que você pode impedir facilmente conflitos de espaço de nome ao vincular.
Dito isto, acredito que seria armazenado na
DATA
seção, que tende a ter variáveis inicializadas com valores diferentes de zero. É claro que esse é um detalhe da implementação, não algo exigido pelo padrão - ele se preocupa apenas com o comportamento, e não com o modo como as coisas são feitas ocultamente.fonte
So, how does a segment of memory (Data Segment) store variables that can be accessed from everywhere (global variables) and also those which have limited scope (file scope or function scope in case of static variables)?
Como encontrar você mesmo com
objdump -Sr
Para realmente entender o que está acontecendo, você deve entender a realocação do vinculador. Se você nunca tocou nisso, considere ler esta postagem primeiro .
Vamos analisar um exemplo do Linux x86-64 ELF para ver por nós mesmos:
Ajuntar com:
Descompile o código com:
-S
descompila o código com a fonte original misturada-r
mostra informações de realocaçãoDentro da descompilação
f
, vemos:e o
.data-0x4
diz que irá para o primeiro byte do.data
segmento.O
-0x4
existe porque estamos usando o endereçamento relativo do RIP, portanto,%rip
na instrução eR_X86_64_PC32
.É necessário porque o RIP aponta para a instrução a seguir , que inicia 4 bytes, após a
00 00 00 00
qual é o que será realocado. Expliquei isso com mais detalhes em: https://stackoverflow.com/a/30515926/895245Então, se modificarmos a fonte
i = 1
e fizermos a mesma análise, concluiremos que:static int i = 0
continua.bss
static int i = 1
continua.data
fonte
É assim que (fácil de entender):
fonte
Depende da plataforma e compilador que você está usando. Alguns compiladores são armazenados diretamente no segmento de código. As variáveis estáticas são sempre acessíveis apenas à unidade de conversão atual e os nomes não são exportados, portanto, as colisões de nomes de razões nunca ocorrem.
fonte
Os dados declarados em uma unidade de compilação serão enviados para o .BSS ou o .Data dos arquivos. Dados inicializados no BSS, não inicializados no DATA.
A diferença entre dados estáticos e globais ocorre na inclusão de informações de símbolos no arquivo. Os compiladores tendem a incluir as informações do símbolo, mas apenas marcam as informações globais como tais.
O vinculador respeita essas informações. As informações de símbolo para as variáveis estáticas são descartadas ou desconectadas, para que as variáveis estáticas ainda possam ser referenciadas de alguma maneira (com opções de depuração ou símbolo). Em nenhum dos casos, as unidades de compilação podem ser afetadas, pois o vinculador resolve primeiro as referências locais.
fonte
Eu tentei com objdump e gdb, aqui está o resultado que eu recebo:
aqui está o resultado objdump
Portanto, suas quatro variáveis estão localizadas no evento de seção de dados com o mesmo nome, mas com deslocamento diferente.
fonte
variável estática armazenada no segmento de dados ou no código, conforme mencionado anteriormente.
Você pode ter certeza de que ele não será alocado na pilha ou na pilha.
Não há risco de colisão, pois a
static
palavra-chave define o escopo da variável como um arquivo ou função; em caso de colisão, existe um compilador / vinculador para avisá-lo.Um bom exemplo
fonte
Bem, essa pergunta é um pouco antiga, mas como ninguém aponta informações úteis: Confira o post 'mohit12379', explicando o armazenamento de variáveis estáticas com o mesmo nome na tabela de símbolos: http://www.geekinterview.com/question_details/ 24745
fonte
A resposta pode muito bem depender do compilador, então você provavelmente deseja editar sua pergunta (quero dizer, mesmo a noção de segmentos não é obrigatória pela ISO C nem pela ISO C ++). Por exemplo, no Windows, um executável não carrega nomes de símbolos. Um 'foo' seria compensado em 0x100, o outro talvez 0x2B0, e o código de ambas as unidades de tradução é compilado sabendo os desvios para o "foo" deles.
fonte
os dois serão armazenados de forma independente; no entanto, se você quiser deixar claro para outros desenvolvedores, poderá agrupá-los em espaços para nome.
fonte
você já sabe que ele armazena em bss (início do bloco por símbolo) também conhecido como segmento de dados não inicializado ou no segmento de dados inicializado.
vamos dar um exemplo simples
a variável estática acima não é inicializada e, portanto, vai para o segmento de dados não inicializados (bss).
e, é claro, inicializado por 10, para o segmento de dados inicializado.
fonte