Pergunta

Estou muito curioso da organização memória de pilha depois de experimentar o que está acontecendo em segundo plano e, obviamente, viu a sua correspondência com o conhecimento minúsculo I adquiridos a partir de livros. Só queria ver se o que eu entendi é correta.

Eu tenho um programa Fundamental - tem 2 funções, primeiro é foo eo outro é o principal (o ponto de entrada).

void foo(){
    // do something here or dont
}

int main(){

    int i = 0;

    printf("%p %p %p\n",foo, &i, main);

    system("PAUSE");
    return EXIT_SUCCESS;
};

A saída do programa é mostrado abaixo, os principais da variável local i fica totalmente em uma posição independente. inteiro é um tipo de valor, mas fez check-lo novamente com um char * ponteiro local para principal e obter resultados semelhantes.

00401390 0022FF44 00401396
Press any key to continue . . .

Eu principalmente entender que código e variáveis ??são alocados em diferentes segmentos de memória (segmento de código / segmento de dados). Então, basicamente, é certo dizer pilha de chamadas desmorona informações básicas sobre a execução de funções (suas variáveis ??locais, parâmetros, retornando pontos) e mantê-los no segmento de dados?

Foi útil?

Solução

Um pouco ressalva no início: todas estas respostas são um pouco afetada pelo sistema operacional e arquitetura de hardware. Windows faz coisas bastante radicalmente diferente do UNIX-like linguagens, sistemas operacionais em tempo real e pequeno-velho sistema UNIX.

Mas a resposta básica como @Richie e @ Paulo disse, é "sim". Quando o compilador e vinculador passar com o código, que é dividido em que são conhecidos como "texto" e "dados" segmentos em UNIX. A segmento de texto contém instruções e alguns tipos de dados estáticos; um segmento de dados contém, assim, os dados.

A grande fatia do segmento de dados é então alocada para a pilha e espaço de pilha. Outros pedaços podem ser alocados para coisas como estruturas estáticas ou de dados externa.

Então, sim, quando o programa é executado, o contador de programa está ativamente buscando instruções de um segmento diferente do que os dados. Agora vamos entrar em algumas dependências de arquitetura, mas, em geral, se você tem memória segmentada suas instruções são construídas de modo a que buscar um byte dos segmentos é tão eficiente quanto possível, No antigo arquitetura 360, eles tinham registros de base , em x86 tem um monte de cabelo que cresceu à medida que o espaço de endereço foi para as antigas 8080 da para processadores modernos, mas todas as instruções são muito cuidadosamente otimizado, porque, como você pode imaginar, as instruções buscar e seus operandos são muito intensivamente utilizado.

Agora, et a arquiteturas mais modernas com a memória virtual e unidade de gerenciamento de memória s. Agora, a máquina tem hardware específico que vamos a tratar do programa do espaço de endereços como uma grande gama plana de endereços; os vários segmentos simplesmente se colocado nesse espaço de endereço virtual bit. O trabalho do MMU é tomar um endereço virtual e traduzi-lo para um endereço físico, incluindo o que fazer se esse endereço virtual não acontecer de ser na memória física em tudo no momento. Novamente, o hardware MMU é muito altamente otimizado, mas isso não significa que não existe não custo de desempenho associado. Mas, como processadores de ter chegado mais rápido e programas goten maior, tornou-se cada vez menos importante.

Outras dicas

Sim, isso é exatamente correto. Código e dados vivem em diferentes partes da memória, com diferentes permissões. A pilha contém parâmetros, endereços de retorno e variáveis ??locais ( "automáticos"), e vive com os dados.

Sim.

Imagine que sua memória código é ROM, e sua memória de dados é RAM (uma arquitetura comum pequeno chip). Então você vê a pilha deve estar na memória de dados.

Bem, eu posso falar para SPARC:

Sim. Quando você executa o programa, o programa é lido duas vezes (pelo menos em SPARC). O programa é carregado na memória, e qualquer destinação Array / pilha são carregados depois. Na segunda passagem através do programa, as pilhas se alocados em memória separado.

Eu não tenho certeza de processadores CISC base, mas eu suspeito que não varia muito.

As suas exposições programa indefinido comportamento especificamente porque:

  • você deixar de incluir <stdio.h> ou <cstdio> dependendo do idioma que você está compilando seu código como
  • printf e todo argumento variável funções não têm a capacidade de-Verifique o tipo de seus argumentos. Por isso, é obrigatória de sua parte para passar argumentos corretamente digitadas. Você realmente deve fazer:
  • system() não tem nenhuma declaração em seu escopo. Incluir <stdlib.h> ou <cstdlib> conforme o caso, talvez.

Escreva o seu código como:

   #include <stdio.h>

   int main() {
      /* ... */
      printf("%p %p %p\n", (void *)foo, (void *)&i, (void *)main);
      /* ... */
   }

Além disso, note que:

  • A definição de void foo() não é um protótipo em C, mas em C ++. No entanto, se você fosse escrever void foo(void) você deseja obter um protótipo em ambas as línguas.
  • system() é dependente de implementação -. Seu código pode não se comportar como esperado em todas as plataformas

A linguagem adequada (C ou C ++) não coloca quaisquer restrições sobre como organizar memória. Ele nem sequer tem o conceito de uma pilha ou uma pilha. Estes são definidos por implementações como eles entenderem. Idealmente, você deve consultar a documentação fornecida pelo seu aplicação para obter uma boa idéia do que eles fazem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top