Ponteiros e memória

Gerenciamento de memória dinâmica em C e C++

Nesta lição, você vai alocar um array cujo tamanho é definido durante a execução e liberar essa memória com segurança.

Introdução

A memória dinâmica é usada quando o tamanho ou o tempo de vida dos dados não pode ser definido na compilação, por exemplo quando a quantidade de elementos depende do que o usuário digita. Essa memória é alocada enquanto o programa roda e precisa ser liberada quando não for mais usada.

Pontos importantes

  • Um ponteiro só deve apontar para um objeto que ainda existe, do tipo certo, ou ser nulo.
  • Cada área de memória alocada deve ser liberada exatamente uma vez.
  • Deixe claro qual função é dona da memória (ownership) e quais dados são apenas lidos (const).

Exemplos de código C e C++

C
Executar →
main.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    size_t count = 5;
    int *values = calloc(count, sizeof *values);
    if (!values) return 1;
    for (size_t i = 0; i < count; ++i) values[i] = (int)(i * i);
    printf("last=%d\n", values[count - 1]);
    free(values);
    return 0;
}
Resultado da execução
last=16
C++
Executar →
main.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values(5);
    for (std::size_t i = 0; i < values.size(); ++i) values[i] = static_cast<int>(i * i);
    std::cout << "last=" << values.back() << '\n';
}
Resultado da execução
last=16

Comparação entre C e C++

Em C, calloc aloca memória para 5 inteiros e os inicializa com 0. O programa precisa verificar se a alocação falhou e chamar free para liberar a memória no final; esquecer disso causa vazamento de memória (memory leak). Em C++, std::vector gerencia a própria memória e a libera sozinho quando deixa de ser usado, mesmo se ocorrer uma exceção.

C

A posse e a liberação da memória ficam totalmente por conta do programador.

C++

Contêineres e RAII liberam os recursos automaticamente quando o objeto chega ao fim da vida.

Exercícios práticos

Execute as duas versões e depois mude o código para observar a diferença de segurança que cada linguagem oferece.

  • Teste ponteiros nulos e falhas na alocação de memória.
  • Execute o programa com AddressSanitizer e UndefinedBehaviorSanitizer para encontrar erros de memória.
  • Anote claramente qual ponteiro é dono da memória e qual só serve para leitura.

Pratique com um desafio

Use o conteúdo desta lição para resolver um problema real. Cada desafio roda no navegador, com testes instantâneos e uma revisão por IA.

Todos os desafios