Alocação de memória

Alocação de memória, em ciência da computação, consiste no processo de solicitar/utilizar memória durante o processo de execução de um programa de computador. A alocação de memória no computador pode ser dividida em dois grupos principais:

  • Alocação Estática: os dados tem um tamanho fixo e estão organizados sequencialmente na memória do computador. Um exemplo típico de alocação estática são as variáveis globais e arrays. A alocação estática de memória tem como principal ponto positivo a simplicidade com que pode ser realizada pelos programadores, mantendo o algoritmo simples e de fácil organização das variáveis utilizadas. No entanto, como principal ponto negativo, a alocação estática ocupa uma porção fixa da memória, em casos em que essas variáveis não sejam utilizadas após um certo ponto, a alocação estática consome desnecessariamente esta porção reservada da memória, podendo levar o programa a fica muito pesado desnecessariamente. Apesar disso, é importante ressaltar, que na maioria das linguagens de programação, as variáveis criadas com alocação estática são liberadas automaticamente após o fim de uma determinada função.[1][2][3]

Em C, um exemplo de alocação estática é simplesmente a declaração de uma variável:

int variavel; //O tipo de dado pode ser qualquer um
  • Alocação Dinâmica: os dados não precisam ter um tamanho fixo, pois é possível definir para cada dado quanto de memória que deseja-se usar. Sendo assim, aloca-se espaços de memória (blocos) que não precisam estar necessariamente organizados de maneira sequencial, podendo estar distribuídos de forma dispersa (não ordenada) na memória do computador. Na alocação dinâmica, é possível alocar/desalocar blocos de memória, de acordo com a necessidade, reservando ou liberando blocos de memória durante a execução de um programa. Para poder “achar” os blocos que estão dispersos ou espalhados na memória usa-se as variáveis do tipo pointer (indicadores de endereços de memória). É importante ressaltar que, na maioria das linguagens de programação que o gerenciamento de memória é manual, ou seja, feito pelo programador, as variáveis criadas com alocação dinâmica não são liberadas automaticamente após o fim de funções, sendo necessário liberá-las manualmente, e, por questões de segurança, é importante atribuir o "NULL" ao ponteiro criado.[1][2][3]

Em C, um exemplo de alocação dinâmica é o seguinte:

int *ponteiro;

ponteiro = (int *) malloc(sizeof(int));
//Nos padrões modernos da linguagem C, (int *) não é necessário.

Dessa forma, o ponteiro aponta para o endereço de memória contendo um espaço do tipo e tamanho da variável int.[4] Em C, um exemplo para limpar a memória alocada é o seguinte:

free(ponteiro);

ponteiro = NULL;

vale ressaltar que, para usar as funções malloc() e free(), é necessário incluir a biblioteca malloc.h.[4]

A pilha (stack) e heap

editar

A pilha e a heap são duas regiões da memória completamente distintas e com usos diferentes.

A pilha é uma região da memória organizada de forma sequencial, ou seja, o primeiro valor a entrar na pilha, é o último a sair dela. A pilha é mais rápida e eficiente que a heap pela sua organização, mas seus valores não podem mudar de tamanho (algo de 8 bits não pode mudar para 16 bits, por exemplo).[1][2][3]

Na maioria das linguagens de programação modernas, a saída dos valores da pilha é automático e acontece quando o escopo acaba. Um exemplo em C seria:

//Não posso acessar as variáveis aqui, pois o escopo nem começou e as variáveis nem foram definidas

int main(void) {
    int x = 1;
    char y = 'A';
    char *z = "Texto";

    return 0;
}

//Também não posso acessá-las aqui, pois o escopo acabou, então elas não são mais acessíveis.

No exemplo acima, o escopo é a área delimitada pelas chaves. Cada uma dessas variáveis é uma variável na pilha, que não pode ser acessada fora do escopo em que foi definida, pois saem da pilha quando ele acaba.

A heap é outra região da memória organizada de forma não sequencial, portanto, ela não tem uma ordem exata. A vantagem da heap é: se uma variável precisar aumentar de capacidade, você pode alocar mais espaço na heap para armazenar um valor maior. Como desvantagem, ela é mais lenta de se acessar e interagir, pois não é sequencial. A alocação de memória na heap é a alocação dinâmica, explicada anteriormente.[1][2][3]

Nas linguagens com gerenciamento de memória manual, a alocação, realocação e desalocação são completamente manuais, por isso são considerados conceitos complexos, além de que podem causar vazamentos de memória.

#include <malloc.h>

int main() {
    int *X = malloc(10 * sizeof(int));
    if (!X) return 1;

    X = realloc(X, 20 * sizeof(int));
    if (!X) return 1;

    free(X);
    X = NULL;

    return 0;
}

O exemplo acima mostra como alocar, realocar e liberar o espaço da memória. Pode parecer simples, mas a dificuldade é tanta que há uma linguagem de baixo nível que evita o gerenciamento de memória manual: Rust. Há várias regras sobre o uso da memória da heap, tornando-o complexo e um assunto difícil de possuir maestria completa.[4]

  Este artigo sobre software é um esboço. Você pode ajudar a Wikipédia expandindo-o.
  1. a b c d «Difference between stack and heap» 
  2. a b c d «Heap vs stack». Blog sobre Ciência da computação - Gustavo Pantuza. 18 de dezembro de 2016. Consultado em 15 de fevereiro de 2025 
  3. a b c d «What is Ownership? - The Rust Programming Language». doc.rust-lang.org. Consultado em 15 de fevereiro de 2025 
  4. a b c «Summary of Malloc (The GNU C Library)». www.gnu.org. Consultado em 15 de fevereiro de 2025