Memória dinâmica: malloc e free
Peça memória em tempo de execução quando você não sabe os tamanhos de antemão - e devolva-a quando terminar.
- Descrever a diferença entre a stack e a heap
- Alocar e liberar memória com
mallocefree - Evitar vazamentos, frees duplos e bugs de uso depois do free
Até aqui, todo array teve um tamanho fixado quando você escreveu o código. Programas reais muitas vezes só descobrem quantos dados existem enquanto rodam - um arquivo de tamanho desconhecido, uma quantidade de itens escolhida pelo usuário. Para isso, o C deixa você pedir memória da heap em tempo de execução.
Stack e heap
- Stack (pilha): onde moram as variáveis locais. A alocação é automática e rápida, e a memória desaparece quando a função retorna. O tamanho dela é limitado (muitas vezes, alguns megabytes).
- Heap: um grande reservatório que você gerencia à mão. Você pede bytes com
malloc, e eles continuam seus - mesmo depois que a função retorna - até você devolvê-los comfree.
malloc e free
1#include <stdio.h>
2#include <stdlib.h>
3
4int main(void) {
5 size_t count = 5;
6 int *numbers = malloc(count * sizeof *numbers);
7 if (numbers == NULL) {
8 fprintf(stderr, "Out of memory\n");
9 return 1;
10 }
11
12 for (size_t i = 0; i < count; i++) {
13 numbers[i] = (int)(i * 10);
14 }
15 for (size_t i = 0; i < count; i++) {
16 printf("%d ", numbers[i]);
17 }
18 printf("\n");
19
20 free(numbers);
21 numbers = NULL;
22 return 0;
23}0 10 20 30 40
O padrão para decorar:
malloc(count * sizeof *pointer)pede bytes suficientes. Usarsizeof *numbers(o tamanho daquilo para o que o ponteiro aponta) continua correto mesmo se você mudar o tipo do elemento depois.- Verifique se é
NULL. OmallocdevolveNULLquando não consegue dar a memória. - Use como um array.
numbers[i]funciona exatamente como antes. - Faça
freeexatamente uma vez quando terminar e depois dê ao ponteiro o valorNULL, para que um segundo uso acidental falhe de forma ruidosa, e não silenciosa.
O malloc não limpa a memória - ela contém lixo. calloc(count, size) aloca e zera. realloc(pointer, new_size) aumenta ou diminui uma alocação (possivelmente movendo-a).
Os três bugs clássicos de memória
| Bug | O que acontece | Prevenção |
|---|---|---|
| Vazamento de memória | Você perde o último ponteiro para uma memória sem liberá-la. Ela continua alocada até o programa terminar. | Todo malloc ganha um free correspondente em todo caminho de saída. |
| Uso depois do free | Você lê ou escreve uma memória depois de liberá-la. Ela pode ter sido reutilizada para outra coisa. | Dê aos ponteiros o valor NULL depois do free. |
| Free duplo | Você libera a mesma memória duas vezes, corrompendo o alocador. | Libere uma vez; free(NULL) é uma operação segura que não faz nada, então zerar com NULL também ajuda aqui. |
Devolvendo memória de uma função
Ao contrário de um array local, a memória da heap sobrevive à função que a alocou - então uma função pode devolvê-la com segurança. A regra que vem junto: documente quem é responsável por chamar o free. Normalmente, "quem recebe libera".
1#include <stdio.h>
2#include <stdlib.h>
3
4// Returns 1..n in a new array. The caller must free() it.
5int *make_range(size_t n) {
6 int *range = malloc(n * sizeof *range);
7 if (range == NULL) {
8 return NULL;
9 }
10 for (size_t i = 0; i < n; i++) {
11 range[i] = (int)i + 1;
12 }
13 return range;
14}
15
16int main(void) {
17 int *numbers = make_range(4);
18 if (numbers == NULL) {
19 return 1;
20 }
21 printf("%d %d %d %d\n", numbers[0], numbers[1], numbers[2], numbers[3]);
22 free(numbers);
23 return 0;
24}1 2 3 4
Principais conclusões
A memória da stack é automática e de vida curta; a memória da heap vive até você fazer
freedela.Aloque com
malloc(count * sizeof *p), sempre verifique se éNULLe façafreeexatamente uma vez, depois dando ao ponteiro o valorNULL.Vazamentos, uso depois do free e free duplo são os bugs clássicos - o AddressSanitizer (
-fsanitize=address) os encontra para você.
Quiz da aula
5 perguntas · aprovação com 4 acertos · até 50 XP
Ao passar, você conclui a aula e mantém sua sequência. As perguntas erradas voltarão em sessões de revisão.
Pratique: escreva código em C
Estes exercícios rodam de verdade. Escreva o programa, clique em “Executar testes” e leia o que o compilador informa: aprender a ler as mensagens do compilador é metade do aprendizado de C.
Exatamente o quanto você precisa
Leia uma quantidade n e depois n inteiros. Guarde-os num array alocado com malloc (exatamente n elementos), imprima a soma deles e faça free do array.
Para 4 e depois 5 10 15 20, imprima 50. Se o malloc falhar, imprima Out of memory e devolva 1.
- Quatro números
- Números negativos
Seu código é compilado com gcc 14 (-Wall -Wextra) e executado no Compiler Explorer (godbolt.org), um serviço público gratuito.
Escreva o seu próprio strdup
Escreva char *duplicate(const char *s), que aloca memória suficiente para uma cópia de s (lembre do terminador!), faz a cópia e a devolve. Devolva NULL se a alocação falhar. A main lê uma palavra, a duplica, troca a primeira letra da cópia por * e imprime as duas.
Para hello, imprima hello *ello.
- hello
- Uma letra
Seu código é compilado com gcc 14 (-Wall -Wextra) e executado no Compiler Explorer (godbolt.org), um serviço público gratuito.
Dúvidas sobre esta lição
Travou em algum ponto? Pergunte. Descobriu algo? Compartilhe. Explicar também é uma ótima forma de aprender.
Carregando publicações…