Um quadro de pilha é um quadro de dados que é empurrado para a pilha. No caso de uma pilha de chamadas, um quadro de pilha representaria uma chamada de função e seus dados de argumento.
Se bem me lembro, o endereço de retorno da função é empurrado primeiro para a pilha, depois os argumentos e o espaço para variáveis locais. Juntos, eles formam o "quadro", embora isso seja provavelmente dependente da arquitetura. O processador sabe quantos bytes existem em cada quadro e move o ponteiro da pilha conforme os quadros são empurrados e removidos da pilha.
EDITAR:
Há uma grande diferença entre as pilhas de chamadas de nível superior e a pilha de chamadas do processador.
Quando falamos sobre a pilha de chamadas de um processador, estamos falando sobre trabalhar com endereços e valores no nível de byte / palavra no código de montagem ou de máquina. Existem "pilhas de chamadas" quando se fala em idiomas de nível superior, mas são uma ferramenta de depuração / tempo de execução gerenciada pelo ambiente de tempo de execução, para que você possa registrar o que deu errado com seu programa (em um nível alto). Nesse nível, coisas como números de linhas e nomes de métodos e classes são frequentemente conhecidos. No momento em que o processador obtém o código, ele não tem absolutamente nenhum conceito dessas coisas.
Se você entender muito bem a pilha, entenderá como a memória funciona no programa e se entenderá como a memória funciona no programa entenderá como o armazenamento de funções no programa e se entenderá como o armazenamento de funções no programa entenderá como funciona a função recursiva e se você entende como a função recursiva funciona, entenderá como o compilador funciona e, se entender como o compilador funciona, sua mente funcionará como compilador e você depurará qualquer programa com muita facilidade.
Deixe-me explicar como a pilha funciona:
Primeiro você precisa saber como as funções são representadas na pilha:
O heap armazena valores alocados dinamicamente.
A pilha armazena valores automáticos de alocação e exclusão.
Vamos entender com o exemplo:
Agora entenda partes deste programa:
Agora vamos ver o que é pilha e o que são partes da pilha:
Lembre-se de uma coisa: se qualquer condição de retorno de uma função for satisfeita, independentemente de ter carregado as variáveis locais ou não, ela retornará imediatamente da pilha com seu quadro de pilha. Isso significa que sempre que qualquer função recursiva satisfizer a condição base e colocarmos um retorno após a condição base, a condição base não esperará para carregar variáveis locais que estão localizadas na parte “else” do programa. Ele retornará imediatamente o quadro atual da pilha, após o qual o próximo quadro está agora no registro de ativação.
Veja isso na prática:
Portanto, agora, sempre que uma função encontra uma instrução de retorno, ela exclui o quadro atual da pilha.
Ao retornar da pilha, os valores retornarão na ordem inversa da ordem original em que foram alocados na pilha.
fonte
hello()
chamou recursivamente ohello()
que chamou (novamente) recursivamentehello()
e o quadro global é a função original que chamou o primeirohello()
?Um rápido encerramento. Talvez alguém tenha uma explicação melhor.
Uma pilha de chamadas é composta por 1 ou muitos quadros de pilha. Cada quadro de pilha corresponde a uma chamada para uma função ou procedimento que ainda não foi finalizado com um retorno.
Para usar um quadro de pilha, um thread mantém dois ponteiros, um é chamado Stack Pointer (SP) e o outro é chamado Frame Pointer (FP). O SP sempre aponta para o "topo" da pilha e o FP sempre aponta para o "topo" do quadro. Além disso, o thread também mantém um contador de programa (PC) que aponta para a próxima instrução a ser executada.
Os seguintes itens são armazenados na pilha: variáveis locais e temporários, parâmetros reais da instrução atual (procedimento, função, etc.)
Existem diferentes convenções de chamada em relação à limpeza da pilha.
fonte
"Uma pilha de chamadas é composta por quadros de pilha ..." - Wikipedia
Um quadro de pilha é algo que você coloca na pilha. São estruturas de dados que contêm informações sobre sub-rotinas a serem chamadas.
fonte
Os programadores podem ter perguntas sobre os quadros de pilha não em um termo amplo (que é uma entidade única na pilha que serve apenas uma chamada de função e mantém o endereço de retorno, argumentos e variáveis locais), mas em um sentido restrito - quando o termo
stack frames
é mencionado em contexto das opções do compilador.Se o autor da pergunta quis dizer isso ou não, mas o conceito de um quadro de pilha do aspecto das opções do compilador é uma questão muito importante, não abordada pelas outras respostas aqui.
Por exemplo, o compilador C / C ++ do Microsoft Visual Studio 2015 tem a seguinte opção relacionada a
stack frames
:O GCC tem o seguinte:
O compilador Intel C ++ possui o seguinte:
que tem o seguinte alias:
O Delphi tem a seguinte opção de linha de comando:
Nesse sentido específico, da perspectiva do compilador, um quadro de pilha é apenas o código de entrada e saída da rotina , que lança uma âncora na pilha - que também pode ser usada para depuração e manipulação de exceções. As ferramentas de depuração podem varrer os dados da pilha e usar essas âncoras para rastreamento, enquanto localizam
call sites
na pilha, ou seja, para exibir os nomes das funções na ordem em que foram chamadas hierarquicamente. Para a arquitetura Intel, épush ebp; mov ebp, esp
ouenter
para entrada e /mov esp, ebp; pop ebp
ouleave
saída.É por isso que é muito importante entender para um programador qual é o quadro de uma pilha quando se trata de opções do compilador - porque o compilador pode controlar se deseja gerar esse código ou não.
Em alguns casos, o quadro da pilha (código de entrada e saída da rotina) pode ser omitido pelo compilador e as variáveis serão acessadas diretamente pelo ponteiro da pilha (SP / ESP / RSP), em vez do conveniente ponteiro base (BP / ESP / RSP). Condições para omissão do quadro da pilha, por exemplo:
A omissão de quadros de pilha (código de entrada e saída para a rotina) pode tornar o código menor e mais rápido, mas também pode afetar negativamente a capacidade dos depuradores de rastrear os dados na pilha e exibi-los ao programador. Essas são as opções do compilador que determinam sob quais condições uma função deve ter o código de entrada e saída, por exemplo: (a) sempre, (b) nunca, (c) quando necessário (especificando as condições).
fonte
O quadro de pilha é a informação compactada relacionada a uma chamada de função. Essas informações geralmente incluem argumentos passados para a função, variáveis locais e para onde retornar após o término. Registro de ativação é outro nome para um quadro de pilha. O layout do quadro da pilha é determinado na ABI pelo fabricante e todos os compiladores que suportam o ISA devem estar em conformidade com esse padrão, no entanto, o esquema do layout pode depender do compilador. Geralmente, o tamanho do quadro da pilha não é limitado, mas existe um conceito chamado "zona vermelha / protegida" para permitir que as chamadas do sistema ... etc. sejam executadas sem interferir no quadro da pilha.
Sempre existe um SP, mas em algumas ABIs (ARM e PowerPC, por exemplo), o FP é opcional. Os argumentos que precisavam ser colocados na pilha podem ser compensados usando apenas o SP. Se um quadro de pilha é gerado ou não para uma chamada de função depende do tipo e número de argumentos, variáveis locais e como as variáveis locais são acessadas em geral. Na maioria dos ISAs, primeiro, os registros são usados e, se houver mais argumentos do que registros dedicados a passar argumentos, eles são colocados na pilha (por exemplo, x86 ABI possui 6 registros para transmitir argumentos inteiros). Portanto, algumas vezes, algumas funções não precisam ser colocadas na pilha, apenas o endereço de retorno é colocado na pilha.
fonte