Por que os livros dizem "o compilador aloca espaço para variáveis na memória". Não é o executável que faz isso? Quero dizer, por exemplo, se eu escrever o seguinte programa,
#include <iostream>
using namespace std;
int main()
{
int foo;
return 0;
}
compile-o e obtenha um executável (que seja program.exe), agora, se eu executar o programa.exe, esse arquivo executável comandará ele próprio para alocar algum espaço para a variável foo. Não é? Por favor, explique por que os livros continuam dizendo: "o compilador fará isso ... fará aquilo".
sizeof
questão agora está localizada em Por que sizeof é chamado de operador em tempo de compilação?Respostas:
Você está certo de que o compilador desapareceu quando o seu programa realmente é executado. E se for executado em uma máquina diferente, o compilador não estará mais disponível.
Eu acho que isso é para fazer uma distinção clara entre a memória realmente alocada pelo seu próprio código. O compilador inserirá algum código no seu programa que faz a alocação de memória (como o uso de comandos new, malloc ou similares).
Portanto, os livros usam "o compilador faz isso ou aquilo" frequentemente para dizer que o compilador adicionou algum código que não é mencionado explicitamente nos seus arquivos de código. É verdade que isso não é exatamente o que está acontecendo. Desse ponto de vista, muitas coisas mencionadas nos tutoriais estariam erradas, mas precisariam de explicações bastante elaboradas.
fonte
malloc
et. al.Depende da variável. O sistema operacional aloca heap, o programa aloca pilha e o compilador aloca espaço para globais / estáticos, ou seja, eles são construídos no próprio exe. Se você alocar 1 MB de memória global, o tamanho do seu exe aumentará em pelo menos 1 MB
fonte
int test[256][1024]; int main(){ test[0][0]=2; return 0; }
Este pequeno programa possui 1 MB alocado, mas só me gera um arquivo de objeto de 1,4 Kb e um executável de 8,4 Kb. Ele deve usar a quantidade correta de RAM, no entanto.int a1=1,a2=2,
... todo o caminho até ..., a1048576=1048576;
Só então você definitivamente obteria algo maior que 1mb, eu acho.o que o compilador fará é pegar seu código e compilá-lo no código da máquina. O que você mencionou é um bom exemplo em que um compilador precisa apenas traduzir.
Por exemplo, quando você escreve
Você pode ver isso como 'Estou dizendo ao compilador para [ na saída que ele gera ] solicitar que o computador reserve RAM suficiente para um int que eu possa referenciar mais tarde. O compilador provavelmente usará uma identificação de recurso ou algum mecanismo para rastrear o foo no código de máquina, você pode usar foo em um arquivo de texto em vez de escrever a montagem! Viva !
Portanto, você também pode olhar para isso, pois o compilador está escrevendo uma carta ( ou talvez uma novela / enciclopédia ) para todos os processadores e dispositivos de destino. A carta é escrita em sinais binários que (geralmente) podem ser traduzidos para diferentes processadores alterando o destino. Qualquer 'carta' e / ou combinação pode estar enviando todos os tipos de solicitações e / ou dados - como, por favor, aloque espaço para essa variável que o programador usou.
fonte
Dizer "o compilador aloca memória" pode não ser factualmente preciso no sentido literal, mas é uma metáfora sugestiva da maneira correta.
O que realmente acontece é que o compilador cria um programa que aloca sua própria memória. Exceto que não é o programa que aloca memória, mas o sistema operacional.
Então, o que realmente acontece é que o compilador cria um programa que descreve seus requisitos de memória e o sistema operacional pega essa descrição e a usa para alocar memória. Exceto que o sistema operacional é um programa e os programas realmente não fazem nada, eles descrevem uma computação executada pela CPU. Exceto que a CPU é realmente apenas um circuito eletrônico complicado, não um homônculo antropomorfizado.
Mas faz sentido pensar em programas, compiladores e CPUs como pessoas pequenas que vivem dentro de um computador, não porque realmente são, mas porque essa é uma metáfora que se encaixa bem no cérebro humano.
Algumas metáforas funcionam bem para descrever as coisas em um nível de abstração, mas não funcionam tão bem em outro nível. Se você pensa no nível do compilador, faz sentido descrever o ato de gerar código que resultará na alocação de memória quando o programa que está sendo compilado for realmente executado como "alocação de memória". É perto o suficiente para que, quando pensemos em como um compilador funcione, tenhamos a idéia certa e não demore tanto tempo para esquecermos o que estávamos fazendo. Se tentarmos usar essa metáfora no nível do programa compilado em execução, ela será enganosa de uma maneira estranha, e foi o que você notou.
fonte
É o compilador que decide onde armazenar uma variável - pode estar na pilha ou em um registro gratuito. Qualquer que seja a decisão de armazenamento tomada pelo compilador, o código de máquina correspondente para acessar essa variável será gerado e não poderá ser alterado em tempo de execução. Nesse sentido, o compilador é responsável por alocar espaço para as variáveis e o program.exe final está agindo cegamente como um zumbi em tempo de execução.
Agora, não confunda isso com gerenciamento de memória dinâmica diferente, como malloc, novo ou pode ser seu próprio gerenciamento de memória. Os compiladores estão lidando com armazenamento e acesso variáveis, mas não se importa com o que um valor real significa em outra estrutura / biblioteca. Por exemplo:
Em tempo de execução, o malloc pode retornar um número arbitrário, mas o compilador não se importa, tudo o que importa é onde armazenar esse número.
fonte
Uma frase mais precisa seria: - "o compilador diz ao carregador para reservar espaço para as variáveis"
Em um ambiente C-ish, haverá três tipos de espaço para variáveis: -
Em um sistema operacional moderno, a memória heap não será realmente reservada, mas alocada conforme necessário.
fonte
Sim, você está certo, neste caso (declarando uma variável em uma função), a frase do seu livro provavelmente está incorreta: quando você declara uma variável em uma função, ela é alocada na pilha ao entrar na função. De qualquer forma, um compilador deve otimizar a situação: se a função não for recursiva (
main()
é uma boa candidata a ela), não há problema em "alocar" o tempo de compilação (no BSS).(Se você está curioso sobre onde suas variáveis residem, você pode verificá-lo de maneira suja (se você não quiser examinar a estrutura do arquivo obj, por que não?), Para poder declarar alguns tipos diferentes de variáveis: constant, estático, dinâmico,
malloc()
alocado etc., e exibe seus endereços (use o%X
formatadorprintf()
para melhor legibilidade) .As variáveis que residem na pilha terão endereços de memória muito diferentes.fonte
A única coisa feita em tempo de execução será aumentar o poinbter da pilha em uma certa quantidade. Portanto, o compilador decide de antemão:
Esse pode ser chamado de "alocação", mas é claro, durante o tempo de compilação, ele ocupa apenas o modelo que o compilador possui do programa em execução.
fonte