Stack e Heap, entenda a estrutura de dados

Em geral, stack (pilha) e heap referem-se a estruturas de dados com propriedades muito especiais. No entanto, este artigo refere-se ao uso específico de fornecimento de memória para um programa executável. Os princípios a seguir se aplicam à maioria das linguagens de programação atuais.

Resumo

  • Stack e heap são partes da RAM.
  • A pilha é uma estrutura de dados LIFO e é muito eficiente.
  • O heap pode ser de qualquer tamanho, mas é mais lento de gerenciar.
  • Os objetos na pilha são liberados automaticamente, enquanto o heap deve ser liberado manualmente.
  • Em algumas linguagens de programação você pode influenciar o uso de Stack e heap.
  • Um vazamento de memória ocorre quando um objeto criado com “novo” no heap não é excluído.
  • O heap é usado para solicitações de memória dinâmica, enquanto a pilha armazena variáveis ​​locais e parâmetros de função.
  • Um heap é uma estrutura de dados para classificação e enfileiramento de prioridade.
  • Um Stack é uma estrutura de dados dinâmica com o princípio LIFO. Novos elementos estão localizados no topo dos elementos existentes na pilha.

Stack (pilha) e heap são partes da RAM

No contexto do gerenciamento de memória no nível do programa, tanto Stack quanto o heap são partes da memória principal disponibilizadas pelo sistema operacional para o programa em execução. Para ser mais preciso, é uma área de memória virtual. Isso significa que o local real de armazenamento físico de um objeto não é conhecido pelo processo. Os dados podem estar em algum lugar em segundo plano na RAM ou até mesmo armazenados no disco rígido.

O nome sugere que os dados aqui estão “uns em cima dos outros”. Isso significa que novos dados só podem ser adicionados por cima. Quando os dados forem liberados novamente, eles serão removidos novamente de cima para baixo. Este princípio também é chamado de LIFO (“Last in, First out”). Devido à sua estrutura, a pilha pode ser gerenciada de forma muito eficiente, razão pela qual as operações da pilha são muito rápidas.

Cada thread de um programa recebe sua própria área de memória com um tamanho fixo para stack. Informações sobre o fluxo do programa (por exemplo, parâmetros de função) e variáveis ​​locais são armazenadas nele. Quando novas variáveis ​​locais são criadas, a pilha aumenta e quando o escopo é deixado, ela diminui novamente e a memória é automaticamente limpa. Os tamanhos típicos de pilha variam entre 64 KB e 8 MB. Geralmente você pode definir o tamanho da pilha no ambiente de desenvolvimento (mesmo que isso normalmente não seja necessário), mas o sistema operacional também pode ter influência.

Criar objeto na pilha

{
// Create a new object on the stack
CExampleClassBase myObject;

// Use o operador '.' para chamadas de função através de variável
meuObjeto.Print ;

} // fim do escopo, variáveis ​​de pilha serão excluídas, o destruidor de myObject será chamado

Este exemplo mostra como um objeto é criado na pilha em C++. As chaves definem um intervalo de visibilidade dentro do qual a variável da pilha permanece válida. Quando o escopo de visibilidade se esgota, o objeto é destruído (o destruidor é chamado) e a pilha é reduzida novamente (ou seja, a memória é liberada novamente).

As propriedades da pilha são resumidas novamente:

  • Tamanho limitado
  • Estrutura de dados LIFO (os últimos dados criados são liberados primeiro, daí a “pilha”)
  • Cresce e diminui à medida que o programa avança
  • Usado para variáveis ​​locais e parâmetros de função
  • Não há necessidade de liberar memória explicitamente
  • Descartar e remover itens é muito eficiente

A pilha (Stack)

O heap não está estruturado como a pilha. Você pode realmente imaginá-lo como uma pilha com muito espaço. Embora o tamanho da pilha seja muito limitado, o heap pode crescer até que o limite de memória no nível do processo seja atingido. No entanto, o heap não é tão fácil de gerenciar internamente, o que o torna mais lento que a pilha. A memória criada no heap também deve ser explicitamente liberada novamente (pelo programador ou, por exemplo, pelo coletor de lixo, dependendo da linguagem de programação).

Ponteiros são usados ​​para acessar o heap, embora isso nem sempre seja imediatamente óbvio. Java e C#, por exemplo, usam referências para objetos localizados no heap. Claro, em segundo plano você ainda terá que trabalhar com ponteiros que contenham o endereço de memória do objeto.

Como os objetos criados no heap não estão limitados à área de visibilidade local, eles podem ser acessados ​​globalmente (desde que um ponteiro ou referência esteja presente).

Criar objeto no heap

// Create a new object on the heap and retrieve pointer to it
CExampleClassBase* myObject = new CExampleClassDerived ;

// Use o operador '->' para chamadas de função através de ponteiro
meuObjeto->Imprimir ;

exclua meuObjeto;
meuObjeto = NULL; // NULL pode ser substituído por 'nullptr' desde C++ 11

Aqui, um objeto é criado em C++ no heap usando o operador new. Após o uso, o objeto deve ser liberado explicitamente novamente com exclusão. A redefinição do ponteiro impede o acesso à memória que já foi liberada, porque a exclusão libera a memória, mas não redefine o ponteiro para NULL. Se a exclusão só for executada posteriormente (por exemplo, quando o programa terminar), o ponteiro poderá ser distribuído arbitrariamente para outros objetos, que também receberão acesso ao objeto.

As propriedades do heap podem ser resumidas da seguinte forma:

  • O heap pode se tornar arbitrariamente grande dentro do limite do processo
  • Criar e liberar objetos é comparativamente lento
  • Objetos criados no heap podem ser disponibilizados globalmente
  • Em linguagens de programação sem coletor de lixo, a memória deve ser liberada manualmente quando não for mais necessária

Aplicativo

Em algumas linguagens de programação (por exemplo, Java) não há influência direta no uso de pilha ou heap. Mas esta opção já existe em C++. Por exemplo, objetos podem ser criados na pilha. Isto faz sentido se o objeto for usado apenas por um curto período de tempo, ou seja, dentro da área de visibilidade. Na maioria das vezes, em C++, você cria objetos na pilha com o operador “novo” e usa a pilha para o resto. Se você esquecer de excluir um objeto criado com “novo”, ocorrerá um vazamento de memória.

FAQ: Perguntas frequentes sobre pilha e heap

Uma solicitação de memória do heap também pode ser chamada de solicitação de memória dinâmica. Os programas o utilizam para ter espaço de buffer que não é ocupado pelo código do programa e pelos campos reservados fixos e pela pilha.

 

Um heap é uma estrutura de dados usada em ciência da computação para classificar dados e criar filas de prioridade.

Um heap pode ser representado como uma árvore e um array. Um heap binário, por exemplo, é uma árvore binária. Cada nó pode ter no máximo dois filhos. Tal como acontece com as estruturas das árvores, a pilha cresce da raiz para baixo e da esquerda para a direita.

Uma pilha é um termo da ciência da computação que se refere a uma estrutura de dados dinâmica. Pode ser suportado diretamente pela maioria dos microprocessadores que usam instruções de máquina.

Pilha Uma área de armazenamento na qual novos elementos são armazenados sobre os elementos existentes. As liberações devem ser feitas na ordem inversa (ou seja, de cima primeiro). (LIFO = Último a entrar, primeiro a sair). Variáveis ​​estáticas Estas variáveis ​​estáticas são criadas no início do programa e excluídas no final do programa.

Programação

Conteúdo Relacionado

Voltar para o blog

Deixe um comentário

Os comentários precisam ser aprovados antes da publicação.