Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Toda a memória além do endereço atual do RSP é considerada volátil: o sistema operacional ou um depurador pode sobrescrever essa memória durante uma sessão de depuração do usuário ou quando um manipulador de interrupção estiver em execução. Portanto, o RSP deve ser sempre definido antes de tentar ler ou gravar valores em um quadro de pilha.
Esta seção discute a alocação de espaço de pilha para variáveis locais e a função intrínseca alloca.
Alocação em pilha
O prólogo da função é responsável por alocar espaço de pilha para variáveis locais, registros salvos, parâmetros de pilha e parâmetros de registro.
A área de parâmetro está sempre na parte inferior da pilha (mesmo se alloca for usada), de modo que ela sempre será adjacente ao endereço retornado durante qualquer chamada de função. Ela contém pelo menos quatro entradas, mas sempre com espaço suficiente para manter todos os parâmetros necessários para qualquer função que possa ser chamada. Observe que o espaço é sempre alocado para os parâmetros de registro, mesmo que os próprios parâmetros nunca sejam hospedados na pilha; um chamador tem a garantia de que o espaço foi alocado para todos os seus parâmetros. Os endereços residenciais são necessários para os registros de argumentos, para que uma área contígua esteja disponível caso a função chamada precise acessar o endereço da lista de argumentos (va_list) ou de um argumento individual. Essa área também fornece um lugar conveniente para salvar argumentos dos registradores durante a execução de thunk e como uma opção de depuração (por exemplo, facilita a localização dos argumentos durante a depuração se eles forem armazenados em seus endereços de origem no código de prólogo). Mesmo que a função chamada tenha menos de quatro parâmetros, essas quatro posições na pilha são efetivamente controladas pela função chamada e podem ser usadas por ela para outras finalidades, além de armazenar valores de registros de parâmetros. Portanto, o chamador não pode salvar informações nessa região da pilha em uma chamada de função.
Se o espaço for alocado dinamicamente (alloca) em uma função, um registro não volátil deverá ser usado como um ponteiro de quadro para marcar a base da parte fixa da pilha e esse registro deverá ser salvo e inicializado no prólogo. Observe que, quando alloca é usado, as chamadas para o mesmo chamador do mesmo chamador podem ter endereços residencial diferentes nos seus parâmetros de registro.
A pilha sempre será mantida alinhada a 16 bytes, exceto dentro do prólogo (por exemplo, depois que o endereço de retorno for enviado por push) e, exceto quando indicado em Tipos de Função para uma determinada classe de funções de quadro.
A seguir, um exemplo do layout de pilha em que a função A chama uma função não terminal B. O prólogo da função A já alocou espaço na parte inferior da pilha para todos os parâmetros de registro e de pilha exigidos por B. A chamada envia por push o endereço de retorno e o prólogo B aloca espaço para suas variáveis locais, registros não voláteis e o espaço necessário para ele chamar funções. Se B usar alloca, o espaço será alocado entre a área de salvamento do registro de variável local/não volátil e a área de pilha de parâmetros.
Quando a função B chama outra função, o endereço de retorno é empilhado logo abaixo do endereço base do RCX.
Construção da área de pilha de parâmetros dinâmicos
Se um ponteiro de quadro for usado, existe a opção de criar dinamicamente a área de pilha de parâmetros. No momento, isso não é feito no compilador x64.
Tipos de função
Existem basicamente dois tipos de funções. Uma função que requer um quadro de execução é chamada de função frame. Uma função que não requer um quadro de pilha é chamada de função folha.
Uma função de quadro é uma função que aloca espaço de pilha, chama outras funções, salva registros não voláteis ou usa tratamento de exceção. Ela também requer uma entrada de tabela de funções. Uma função de quadro requer um prólogo e um epílogo. Uma função de quadro pode alocar dinamicamente o espaço de pilha e pode empregar um ponteiro de quadro. Uma função de quadro tem as funcionalidades completas desse padrão de chamada à sua disposição.
Se uma função de quadro não chamar outra função, então não é necessário alinhar a pilha (referenciada na Seção Alocação de Pilha).
Uma função folha é aquela que não requer uma entrada de tabela de funções. O sistema não pode fazer alterações em qualquer registro não volátil, incluindo o RSP, o que significa que ele não pode chamar funções ou alocar espaço na pilha. É permitido deixar a pilha desalinhada enquanto executa.
Alinhamento de malloc
Malloc tem a garantia de retornar memória adequadamente alinhada para armazenar qualquer objeto que tenha um alinhamento fundamental e que possa caber na quantidade de memória alocada. Um alinhamento fundamental é um alinhamento menor ou igual ao maior alinhamento suportado pela implementação sem uma especificação de alinhamento. (No Microsoft C++, esse é o alinhamento necessário para um doubleou 8 bytes. No código destinado a plataformas de 64 bits, são 16 bytes.) Por exemplo, uma alocação de quatro bytes seria alinhada em um limite que dá suporte a qualquer objeto de quatro bytes ou menor.
O Visual C++ permite tipos que têm alinhamento estendido, que também são conhecidos como tipos alinhados demais. Por exemplo, os tipos SSE __m128 e __m256, e os tipos declarados usando __declspec(align( n )) em que n é maior que oito, têm alinhamento estendido. O alinhamento de memória num limite adequado para um objeto que requer alinhamento estendido não é garantido por malloc. Para alocar memória para tipos com sobrealinhamento, use _aligned_malloc e funções relacionadas.
alloca
_alloca é necessário para ser alinhado em 16 bytes e, além disso, necessário para usar um ponteiro de quadro.
A pilha alocada precisa incluir espaço depois dela para parâmetros de funções chamadas posteriormente, conforme discutido na Alocação de Pilhas.