Memória

Ao longo da nossa carreira, é comum ouvirmos termos como Stack e Heap. Muitas vezes, acabamos deixando esse conhecimento para depois, por acreditar que seja algo exclusivo de 'baixo nível'. Hoje, vou explicar um pouco sobre o layout da memória e mostrar onde esses conceitos — e tantos outros — se encaixam.

Antes de começarmos, deixo aqui uma imagem ilustrativa do layout de memória. Vamos seguir nosso estudo partindo do endereço mais alto até o mais baixo.

Layout de uma Memória
Layout de uma memória
Fonte: Próprio Autor

Kernel

Uma das primeiras coisas que a arquitetura de memória define é o espaço do Sistema Operacional (Kernel Space). Ele ocupa os endereços mais altos para garantir que o 'cérebro' do computador tenha uma área reservada e protegida, permitindo que todos os outros processos funcionem com segurança abaixo dele.

Layout de Memória - Kernel
Kernel
Fonte: Próprio Autor

Ambiente

Com o Kernel já residente na memória, o sistema prepara as variáveis de ambiente. Essas variáveis funcionam como um guia de configuração para os programas, definindo o 'cenário' onde eles serão executados e permitindo que saibam onde encontrar arquivos e recursos do sistema.

Layout de Memória - Ambiente
Ambiente
Fonte: Próprio Autor

Argumentos

Depois que o sistema inicializa e as variáveis de ambiente são carregadas, a memória organiza os Argumentos, que são as instruções extras que dizem como o programa deve começar.

Layout de Memória - Argumentos
Layout de Memória - Argumentos
Fonte: Próprio Autor

A quantidade de argumentos vem logo depois, até porque o sistema precisa saber exatamente quantas instruções ele recebeu, garantindo assim que ele processe cada uma delas na ordem certa para tudo funcionar como deveria.

Layout de Memória - Quantidade de Argumentos
Layout de Memória - Quantidade de Argumentos
Fonte: Próprio Autor

Dados das Funções

Agora que entendemos como o sistema se organiza, chegamos aos Dados das Funções. É nesta área que o programa ganha vida, as funções são empilhadas e executadas conforme a necessidade, lembrando que a primeira a ser chamada é a main.

Layout de Memória - Dados das Funções
Layout de Memória - Dados das Funções
Fonte: Próprio Autor

Stack

Para facilitar nosso entendimento podemos visualizar esse bloco como uma Pilha (Stack), no topo (endereços mais altos), o sistema injeta o Ambiente e os Argumentos com sua Quantidade (argc). Imediatamente abaixo, a execução começa e a pilha continua crescendo para baixo conforme os Dados das Funções e suas variáveis locais são criadas. Logo, uma estrutura única, onde o contexto do sistema e a execução do código convivem.

Layout de Memória - Pilha (Stack)
Layout de Memória - Pilha (Stack)
Fonte: Próprio Autor

Espaço Disponível

Como a alocação de memória ocorre de forma dinâmica, tanto a Stack quanto o Heap podem expandir conforme as necessidades do programa. Por isso, a arquitetura reserva um Espaço Disponível entre ambos: a Stack cresce para baixo e o Heap para cima. Caso a demanda de memória seja excessiva e as duas áreas se encontrem, ocorre uma colisão conhecida como estouro de memória (Memory Overflow).

Layout de Memória - Espaço Disponível
Layout de Memória - Espaço Disponível
Fonte: Próprio Autor

Memória Mapeada

Em vez de carregar o arquivo inteiro para a RAM, o sistema operacional estabelece um vínculo lógico entre a memória e o armazenamento. Os dados são carregados em 'páginas' apenas quando acessados, o que otimiza o uso de recursos e acelera a execução, especialmente em arquivos grandes ou bibliotecas compartilhadas.

Layout de Memória - Memória Mapeada
Layout de Memória - Memória Mapeada
Fonte: Próprio Autor

Heap

A alocação dinâmica é quando o seu programa pede um pedaço de memória enquanto está rodando, porque ele não sabe de antemão de quanto espaço vai precisar. Alguns problemas bem comuns da programação acontece aqui, pois você pode alocar memória, porém tem que depois lembrar de liberar essa memória alocada.

Layout de Memória - Heap
Layout de Memória - Heap
Fonte: Próprio Autor

.bss

.bss é uma seção específica da memória de um programa que armazena variáveis globais e estáticas que foram declaradas, mas não foram inicializadas com nenhum valor específico.

Layout de Memória - .bss
Layout de Memória - .bss
Fonte: Próprio Autor

.data

Enquanto o .bss cuida do que está "vazio", o .data é responsável por armazenar todas as variáveis globais e estáticas que você já inicializou com um valor específico no seu código.

Layout de Memória - .data
Layout de Memória - .data
Fonte: Próprio Autor

.rodata

.rodata é o segmento de memória destinado exclusivamente a dados que o programa pode ler, mas nunca alterar durante a execução.

Layout de Memória - .rodata
Layout de Memória - .rodata
Fonte: Próprio Autor

.text

É no .text que o seu código realmente vive depois de ser transformado em linguagem de máquina, armazenando as instruções binárias.

Layout de Memória - .text
Layout de Memória - .text
Fonte: Próprio Autor

Caso queira continuar estudando e aprender mais sobre outros conteúdos, segue o link. Bons estudos!

"A beleza que vive no ato de compartilhar algo com o outro." — Monja Coen