Segmentation Fault: não apenas um erro, mas uma porta para o mundo da memória em C++
Se você já escreveu em C++ e viu no terminal a mensagem curta, mas assustadora Segmentation fault (core dumped), saiba que não está sozinho. Esse sinal é um dos inimigos mais comuns de desenvolvedores iniciantes (e experientes). No Stack Overflow, a pergunta "What is a segmentation fault?" acumulou centenas de milhares de visualizações. Mas por trás desse erro, esconde-se algo maior: uma compreensão profunda de como funcionam a memória, os ponteiros e o desempenho do seu código.
Neste artigo, não vamos apenas explicar o que é segfault. Vamos aprender a encontrá-lo, corrigi-lo e, principalmente, preveni-lo. E, de quebra, descobrir como esse erro está relacionado à otimização de código e por que sua ocorrência pode indicar problemas de desempenho.
O que é segmentation fault em termos simples?
Segmentation fault (erro de segmentação) é um sinal do sistema operacional para o seu programa: "Você está tentando acessar uma memória que não lhe pertence". Imagine que você aluga um apartamento (seu processo) e de repente tenta entrar no vizinho atravessando a parede. O segurança (SO) te para e te expulsa do prédio.
Em C++, isso ocorre quando o programa acessa um endereço de memória inválido. Por exemplo, um ponteiro nulo, memória já liberada ou fora dos limites de um array. Diferente de Java ou Python, onde a máquina virtual é responsável pela segurança da memória, o C++ oferece controle total. E com controle, vem a responsabilidade.
Como isso aparece no código?
#include <iostream>
int main() { int* ptr = nullptr; // ponteiro nulo *ptr = 42; // segmentation fault! return 0;}À primeira vista, o erro é óbvio. Mas em projetos reais, as causas podem ser muito mais sutis. Vamos analisá-las em ordem.
Top 5 causas de segmentation fault em C++
1. Desreferenciamento de ponteiro nulo
A causa mais comum e compreensível. O ponteiro não aponta para nenhum objeto, e você tenta gravar ou ler dados nesse endereço.
int* p = nullptr;std::cout << *p; // segfaultComo evitar: sempre verifique os ponteiros antes de usá-los:
if (p != nullptr) { std::cout << *p;}2. Acesso fora dos limites do array
C++ não verifica índices de arrays. Se você acessar arr[100] quando o array tem apenas 10 elementos, estará lendo ou escrevendo em memória alheia.
int arr[10];arr[15] = 5; // potencial segfaultIsso é particularmente traiçoeiro, pois o erro pode não aparecer imediatamente, mas surgir depois em um local completamente diferente do programa. Esses bugs são muito difíceis de depurar.
3. Uso após liberação (use-after-free)
Você liberou a memória (delete ou free), mas continua usando o ponteiro para ela. A memória pode já ter sido atribuída a outro processo ou sobrescrita.
int* ptr = new int(10);delete ptr;*ptr = 20; // segfault — uso após liberaçãoDica: após delete, atribua nullptr ao ponteiro.
delete ptr;ptr = nullptr;4. Estouro de pilha (stack overflow)
Embora não seja um segfault clássico, o estouro de pilha frequentemente leva ao mesmo sinal. Isso ocorre quando você cria muitas variáveis locais ou entra em recursão infinita.
void infinite() { int huge[1000000]; // array muito grande na pilha infinite(); // recursão sem saída}5. Uso incorreto de reinterpret_cast
A conversão de tipos em C++ é uma ferramenta poderosa, mas perigosa. Se você interpretar a memória incorretamente, o segfault não tardará a aparecer.