A pilha de chamadas começa na parte inferior ou superior?


10

Uma pilha é algo que se empilha de baixo para cima.

Portanto, uma pilha de chamadas adiciona novos itens na pilha quando as funções são chamadas com os itens sendo removidos da pilha, pois cada função termina até que a pilha esteja vazia e, em seguida, o programa termina.

Se o exposto acima estiver correto, por que as pessoas se referem ao controle "subindo" a pilha de chamadas? Certamente o controle desce a pilha de chamadas até chegar ao fundo.


Quando uma função é chamada, um item é adicionado ao topo da pilha e o controle é passado para essa função. Portanto, o controle se move do item subjacente na pilha para o item superior - para cima.
treecoder

11
@greengit: a expressão "up the call stack" é usada com exceções, onde o controle realmente se move na direção oposta.
Michael Borgwardt

@ MichaelBorgwardt: Você está correto.
treecoder

11
@ MichaelBorgwardt: Vi a expressão "erros subirem na pilha de chamadas". Certamente isso está incorreto.
CJ7

Respostas:


8

Existem dois motivos possíveis para esse uso:

  • No contexto de exceções, o controle se move para a função / método de chamada, e essa hierarquia de chamada é normalmente visualizada com o método principal na parte superior e as chamadas de método formando uma hierarquia para baixo, com um nível decrescente de abstrações. Nesta hierarquia, uma exceção se move para cima.

  • A pilha real do programa em um aplicativo x86 normal é invertida, ou seja, cresce para baixo. As instruções do código da máquina PUSH / PUSHW / PUSHD diminuem o ponteiro da pilha. Outras arquiteturas podem compartilhar esse modelo.


A idéia de cima para baixo não é contrária ao conceito cotidiano de uma "pilha" ser uma pilha de itens que começam na parte inferior?
CJ7

@ CraigJ: assim é o fato de que os bits de cada byte do conteúdo da pilha serão fisicamente armazenados em chips separados. Quem se importa?
Michael Borgwardt

1

Tudo depende da definição de palavras; o que exatamente você quer dizer com as palavras "superior" e "inferior" neste contexto e também na implementação do sistema operacional ou da arquitetura do computador.

Lembro-me do seguinte há muito tempo, quando estava programando no Commodore 64. A memória entre o endereço $ 0800 (2048) e $ 9FFF (40959) foi reservada para programas BASIC. O código do seu programa BASIC foi armazenado começando no endereço mais baixo (US $ 0800, crescendo a partir daí). A pilha, para armazenar variáveis ​​e endereços de retorno de sub-rotinas, começou no topo (US $ 9FFF) desse intervalo e cresceu para endereços mais baixos. Portanto, nesse contexto, era lógico ver a pilha crescendo para baixo e, quando você retorna de uma sub-rotina, o quadro da pilha da sub-rotina é descartado incrementando o ponteiro da pilha, para que você possa dizer que está "subindo a pilha" quando retornando de uma sub-rotina.

Não sei como ele funciona em versões modernas, por exemplo, de processadores Windows ou Intel x86. Talvez a pilha funcione ao contrário, ou seja, ela cresça de endereços mais baixos para mais altos. Se esse for o caso, você provavelmente usaria as palavras "superior", "inferior" e "para cima", "para baixo" exatamente o contrário.


0

Para chamar uma função como foo (6, x + 1) ...

  1. Avalie as expressões de parâmetro reais, como x + 1, no contexto do chamador.
  2. Aloque memória para os locais de foo () empurrando um "bloco local" adequado de memória para uma "pilha de chamadas" de tempo de execução dedicada a esse propósito. Para parâmetros, mas não variáveis ​​locais, armazene os valores da etapa (1) no slot apropriado no bloco local de foo ().
  3. Armazene o endereço de execução atual do chamador (seu "endereço de retorno") e alterne a execução para foo ().
  4. foo () executa com seu bloco local convenientemente disponível no final da pilha de chamadas.
  5. Quando foo () é concluído, ele sai removendo os habitantes locais da pilha e "retorna" para o chamador usando o endereço de retorno armazenado anteriormente. Agora, os locais do chamador estão no final da pilha e ele pode retomar a execução.

Referência:

http://cslibrary.stanford.edu/102/PointersAndMemory.pdf (p15)


Observe que isso é altamente específico para a convenção de chamada. Há convenções de chamada que permitem que o chamador limpar, mais usar pelo menos alguns registros, etc.

0

Se você conceitua uma pilha como uma coisa de baixo para cima, como um cilindro com bolas de tênis sob a realidade gravitacional normal, o controle então sobe na pilha conforme as funções são chamadas. À medida que as funções são concluídas, o controle desce a pilha.

Se você conceituar uma pilha como uma coisa de cima para baixo, como o mesmo cilindro de bolas de tênis, mas com gravidade invertida, o controle move-se para baixo na pilha à medida que as funções são chamadas e na pilha quando as funções são concluídas.

Estes são apenas modelos na sua cabeça e são essencialmente totalmente arbitrários. Você pode conceituá-lo como algo de um lado para o outro, se preferir, mas pode ter problemas para se comunicar com as pessoas. Pessoalmente, acho que se A chama B e B chama C, C é o fundo da pilha (realidade gravitacional invertida) e, se uma exceção ocorre em C, você deseja colocar essa exceção "até" em bolha. Acho que esse pode ser o uso de linguagem mais comum, porque a sensação é de que C é profundo e A é o topo. A primeira função é mais intuitivamente a parte superior para mim e as funções ficam mais profundas a cada chamada.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.