Pular para conteúdo

Erros comuns do compilador

Uma coletânea das mensagens de erro mais frequentes do curso, com o que elas realmente significam e como resolver. Se você travou num erro, procure aqui antes de pedir ajuda — boa parte já está catalogada.

Erros de compilação (o g++ recusa gerar o executável)

error: ‘X’ was not declared in this scope

Você usou um nome (std::cout, std::string, uma função sua) que o compilador não conhece nesse ponto. Causas mais comuns:

  • Faltou #include (ex.: <iostream> para std::cout, <string> para std::string, <vector> para std::vector).
  • Faltou o prefixo std:: e você não tem using namespace std;.
  • Você está chamando uma função antes de declará-la (em C++, diferente de algumas linguagens, o compilador processa o arquivo de cima para baixo — a declaração precisa vir antes do uso).
  • Erro de digitação no nome.

error: expected ‘;’ before ...

Falta um ; no fim de alguma linha antes da apontada pelo erro — o compilador só percebe o problema quando já leu além do ponto onde o ; deveria estar. Olhe a linha anterior primeiro.

error: expected ‘}’ at end of input / error: expected declaration before ‘}’ token

Chaves {/} desbalanceadas em algum lugar do arquivo — sobrou ou faltou uma. Editores com destaque de chave correspondente (a maioria) ajudam a achar o desbalanceamento.

error: invalid initialization of non-const reference from an rvalue

Você tentou passar um valor temporário (uma expressão como 2 + 3, ou o retorno de uma função) para um parâmetro T& (referência não-const). Referência não-const exige uma variável de verdade para se ligar. Se a função só vai ler o valor, mude o parâmetro para const T&.

error: no matching function for call to ...

Você chamou uma função/método com argumentos que não batem com nenhuma versão disponível — tipo errado, número errado de argumentos, ou (com sobrecarga) nenhuma versão aceita exatamente essa combinação. A mensagem completa costuma listar as opções disponíveis logo abaixo — compare com o que você passou.

error: use of deleted function ‘X::X()’

Você tentou criar um objeto sem argumentos (MinhaClasse obj;), mas a classe só tem construtor(es) que exigem argumentos (e o compilador, por isso, não gera um construtor padrão). Forneça os argumentos exigidos.

error: passing ‘const X’ as ‘this’ argument discards qualifiers

Você chamou um método não-const a partir de um objeto/referência const (por exemplo, um parâmetro const MinhaClasse&). Métodos que alteram o objeto não podem ser chamados quando ele está marcado const. Se o método só lê os campos, marque-o como const.

error: cannot declare variable ‘x’ to be of abstract type ‘X’

Você tentou criar diretamente um objeto de uma classe abstrata (que tem pelo menos um método virtual puro, = 0). Crie uma classe filha que implemente todos os métodos puros, e instancie a filha.

error: no match for ‘operator[]’ (em map/set const)

Você tentou usar [] num map/set que chegou como const (por exemplo, const std::map<...>& m, e m[chave]). operator[] pode inserir uma chave nova, o que alteraria o container — por isso não existe versão const dele. Use .at(chave) (lança exceção se não existir) ou .find(chave)/.count(chave) para leitura seg.

redefinition of class ‘X’ / redefinition of ‘...’

Falta um include guard (#ifndef/#define/#endif) no .h, ou ele está mal escrito (nome de macro repetido em dois arquivos diferentes). Veja o capítulo 12.

Erros de linkedição (o g++ compila cada arquivo, mas falha ao juntar tudo)

undefined reference to ‘Classe::metodo(...)’

Você declarou metodo no .h mas esqueceu de:

  • implementá-lo em algum .cpp, ou
  • incluir esse .cpp na linha de compilação (g++ main.cpp faltou_esse.cpp -o programa).

Veja o capítulo 12 — é sempre um dos dois.

undefined reference to ‘main’

Nenhum dos arquivos compilados tem uma função main(). Confira se você incluiu o arquivo certo na compilação.

Quando um teste falha (Assertion failed)

Assertion failed: (expr), function main, file X, line N. (ou similar) e o programa encerra

Isso não é um erro de compilação nem um bug do seu programa em si — é o assert() (de <cassert>) usado pelos testes de cada exercício avisando que uma condição esperada deu falsa. X:N diz em qual arquivo e linha o teste parou; expr é a condição exata que falhou (compare com o que sua função deveria devolver ali). O programa para imediatamente nesse ponto — os testes que viriam depois dessa linha nunca chegam a rodar. Corrija a lógica da sua função (nunca a linha do assert em si, que é o teste — não a solução), recompile e rode de novo: se havia mais de um problema, o próximo assert que falhar vai aparecer na vez dele.

Avisos do compilador (o programa compila, mas o g++ reclama)

Aviso não é erro: o executável é gerado do mesmo jeito. Mas todo aviso do -Wall -Wextra aponta para algo que o compilador julgou suspeito o bastante para interromper você — trate como defeito a corrigir, não como ruído a ignorar.

warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type'

Você comparou um int com o resultado de .size(), que é std::size_t — um tipo sem sinal. Para comparar, o compilador precisa converter um dos lados, e há valores em que essa conversão dá o resultado errado. Duas correções, e a escolha depende do laço (capítulo 4):

  • índice que só anda para frente: declare std::size_t i = 0;
  • índice que entra em conta que pode ficar negativa (i - 1, n - passada, percorrer de trás para frente): guarde int n = static_cast<int>(v.size()); antes do laço e compare com n.

warning: unused parameter 'x' / unused variable 'x'

Você declarou algo que nunca usou — muito comum em stub de exercício ainda não implementado, e nesse caso é esperado. Se não for esse o caso, geralmente indica que você esqueceu de usar o parâmetro que deveria ter usado (ou usou outro no lugar dele por engano).

Comportamento errado sem erro de compilação (os mais perigosos)

O programa compila e roda, mas imprime a versão "errada" de um método sobrescrito

Falta virtual na classe base. Sem ele, a chamada é resolvida em tempo de compilação pelo tipo da referência/ponteiro, não pelo tipo real do objeto — veja o capítulo 11.

O laço nunca termina, ou lê memória alheia num container vazio

Quase sempre é size() sem sinal. Como std::size_t nunca é negativo, num vector vazio v.size() - 1 não dá -1: dá o maior número que cabe no tipo (18446744073709551615 em 64 bits). Assim, for (std::size_t i = 0; i < v.size() - 1; i++) num vector vazio percorre memória que não é sua, e for (std::size_t i = v.size() - 1; i >= 0; i--) não termina nunca, porque i >= 0 é sempre verdadeiro. Em ambos os casos, guarde o tamanho em int n = static_cast<int>(v.size()) antes do laço. Veja o capítulo 4.

"double free or corruption", ou crash aleatório perto do fim do programa

Quase sempre cópia rasa de uma classe que gerencia um ponteiro bruto (new/delete manual) sem construtor de cópia customizado. A correção, na maioria dos casos, é a regra do zero: trocar o ponteiro bruto por vector/string/unique_ptr — veja o capítulo 10.

O programa usa cada vez mais memória ao longo do tempo, sem crash imediato

Vazamento de memória: algum new sem delete correspondente em algum caminho do código. Ferramentas como -fsanitize=address (compile com essa flag extra) ou Valgrind detectam isso automaticamente.

std::cin >> variavel seguido de std::getline "pula" a leitura

>> deixa o \n da tecla Enter no buffer de entrada, e a próxima chamada a std::getline lê essa linha vazia. Se você precisar misturar os dois, descarte o \n restante antes do getline (fora do escopo detalhado deste curso, mas saiba que o problema tem nome).

Comparação de double/float com == às vezes falha "sem motivo"

Ponto flutuante tem erro de arredondamento inerente à representação binária. Nunca compare com == — use uma margem de tolerância, como os testes do curso fazem: assert(std::abs(obtido - esperado) <= 0.0001); (precisa de #include <cmath>).