Olhando para Layout de memória de um processo de execução no Linux.
- User Stack = armazena todas as variáveis locais de uma função e também outros dados da função como registradores,endereços de retorno, etc.
- Runtime heap = memória compartilhada por todos os processos em execução no sistema operacional, usado para a Alocação Dinâmica de Memória.
- Read-Write segment = armazena todas as variáveis globais de um programa.
- Read-only segment = armazena o código do programa.
- Podemos no Linux verificar o quanto de memória temos para o programa usando o comando
ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
...
stack size (kbytes, -s) 8192 <--- ESTE AQUI
cpu time (seconds, -t) unlimited
max user processes (-u) 15333
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
- Neste caso o tamanho da pilha é limitado a 8 Mb.
Alocação Dinâmica de Memória resolve o problema de armazenar grandes quantidade de dados na pilha da memória. Também nos permite alocar memória que irá persistir além do escopo da função que estamos fazendo.
- Lembre-se sempre que a Alocação Dinâmica de Memória usa a memória runtime heap.
- Precisamos usar funções para gerenciar memória dinâmicamente.
- Usamos o Header
stdlib.h
para mexermos com a alocação. - As seguintes funções são usadas dessa biblioteca:
- é a função mais simples! ela tenta alocar o número de bytes de memória e retorna um ponteiro para o bloco(se falhar vai dar NULL).
- o número de bytes é o sizeof() do tipo de dado que queremos mais a multiplicação de quantas posições desejamos, por exemplo de um vetor.
Exemplo: criando um vetor de 10 posições em um ponteiro.
// Criando o Ponteiro com 10 espaços na memória
int* ptr = malloc(sizeof(int)*10);
// Criando de uma forma mais segura
int* ptr = malloc(10 * sizeof *ptr);
- A função calloc aloca memória para um array de tamanho definido onde cada posição requer um número definido de bytes.
- O calloc inicia a memória com Zeros, onde o malloc não faz isso.
// Criando o Ponteiro com 10 espaços na memória
int* ptr = calloc(10, sizeof *ptr); //inicia tudo com zero
- A função realloc altera o tamanho de ponteiro já com a memória alocada.
- Se é maior e não cabe, a função irá mover a memória para outro lugar e liberar o ponteiro original.
- Retorna um ponteiro para o novo bloco que agora foi alocado.
// Ponteiro anteriormente alocado
int* ptr = calloc(10, sizeof *ptr);
// Aumentando o tamanho para mais 20
int* nptr = realloc(ptr, 30);
- Para liberar memória alocada dinâmicamente, precisamos chamar a função
free
para podermos liberar a memória para utilizar em outro lugar. - Precisamos passar o ponteiro que usamos para utilizar a memória alocada.
- atenção, em C não existe Garbage Collection por isso precisamos sempre no final liberando a memória que não estamos mais usando dinâmicamente.
// Ponteiro com memória alocada
int* ptr = malloc(10 * sizeof *ptr);
// Liberando a memória
free(ptr);