C++ Mensagens de Erro

O compilador de C++ é exigente e fala inglês. Quando algo dá errado, ele escreve o arquivo, a linha, a coluna e uma frase curta, às vezes seguida de dezenas de linhas de "notas". Esta página junta as mensagens que você mais vai encontrar: de compilação, de ligação e de execução. Cada uma vem com o código que a provoca, o que ela quer dizer, como consertar e a aula onde o assunto é explicado. Todas foram provocadas de verdade no g++ 15.2 e no clang++ 21 da máquina da Ana.

Como usar esta página
  • Copie um pedaço da mensagem que apareceu para você (por exemplo, was not declared) e procure aqui com Ctrl+F.
  • Os programas ficam na pasta ~/erros da Ana. No seu computador, o nome do arquivo e o número da linha serão outros; o texto da mensagem é o mesmo.
  • As mensagens do g++ saem em inglês, com aspas tipográficas ‘assim’. As do ligador (ld) e do terminal saem em português na máquina da Ana, porque esses programas têm tradução instalada; a versão em inglês aparece logo ao lado.
  • O editor do guia usa o Clang, não o g++. Por isso, os 10 erros mais comuns têm as duas versões lado a lado. Veja também O Editor do Guia.
  • Todos os programas foram compilados com o comando padrão do guia: g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa (veja Compilar com g++).

Atalhos: Ler uma mensagem · Compilação, ligação ou execução? · Os 10 mais comuns (g++ × clang++) · Outros erros de compilação · Mensagens gigantes · Avisos · Erros de ligação · Erros de execução · Códigos de saída · Sanitizers


Como ler uma mensagem do g++

A Ana escreveu um programa para a lojinha com três descuidos: esqueceu um ;, esqueceu o std:: e digitou um nome errado.

#include <iostream>

int main() {
    int preco = 10
    int quantidade = 3;
    cout << "Total: " << preco * quantidade << '\n';
    std::cout << "Itens: " << quantdade << '\n';
}
$ g++ -std=c++23 -Wall -Wextra loja.cpp -o loja
loja.cpp: In function ‘int main()’:
loja.cpp:5:5: error: expected ‘,’ or ‘;’ before ‘int’
    5 |     int quantidade = 3;
      |     ^~~
loja.cpp:6:5: error: ‘cout’ was not declared in this scope; did you mean ‘std::cout’?
    6 |     cout << "Total: " << preco * quantidade << '\n';
      |     ^~~~
      |     std::cout
In file included from loja.cpp:1:
/usr/include/c++/15/iostream:65:18: note: ‘std::cout’ declared here
   65 |   extern ostream cout;          ///< Linked to standard output
      |                  ^~~~
loja.cpp:6:34: error: ‘quantidade’ was not declared in this scope
    6 |     cout << "Total: " << preco * quantidade << '\n';
      |                                  ^~~~~~~~~~
loja.cpp:7:31: error: ‘quantdade’ was not declared in this scope
    7 |     std::cout << "Itens: " << quantdade << '\n';
      |                               ^~~~~~~~~
$ echo $?
1
PedaçoO que quer dizer
loja.cpp: In function ‘int main()’:Contexto: "dentro da função main". Não é um erro; diz onde estão os próximos.
loja.cpp:5:5:Arquivo:linha:coluna. Linha 5, coluna 5. Seu editor pula direto para lá.
error:O tipo: error impede o programa de ser criado; warning (aviso) deixa criar, mas avisa de algo suspeito; note (nota) é uma informação extra sobre a mensagem anterior.
expected ‘,’ or ‘;’ before ‘int’O texto: "esperava , ou ; antes de int". O erro está no fim da linha 4, mas o compilador só percebe na linha 5, quando encontra o int.
5 | int quantidade = 3;
| ^~~
A linha do código, com o ^ apontando a coluna e os ~ sublinhando o trecho.
| std::coutUma sugestão de conserto, escrita embaixo do trecho.
In file included from …
note: ‘std::cout’ declared here
Uma nota apontando para dentro da biblioteca, só para mostrar onde o std::cout existe. Você não mexe nesse arquivo.
[-Wunused-variable], [-fpermissive]No fim de algumas mensagens: o nome da opção ligada a ela. [-Wxxx] é o nome do aviso (veja Avisos). [-fpermissive] quer dizer que uma opção antiga transformaria o erro em aviso: não use, conserte o código.
Regra de ouro: conserte o primeiro erro e compile de novo

Repare no terceiro erro: ‘quantidade’ was not declared. Mas a variável está declarada na linha 5! Por causa do ; que faltou, o compilador entendeu as linhas 4 e 5 como uma coisa só e "perdeu" a declaração. Um erro costuma provocar outros, em cascata. Por isso: leia o primeiro, conserte, compile de novo. A aula Lendo Erros do Compilador treina isso com calma.

Missão: este é o programa da lojinha. Clique em Rodar, leia as mensagens (aqui elas vêm do Clang, com outras palavras) e conserte os três erros até aparecer Total: 30 e Itens: 3.

#include <iostream>

int main() {
    int preco = 10
    int quantidade = 3;
    cout << "Total: " << preco * quantidade << '\n';
    std::cout << "Itens: " << quantdade << '\n';
}
#include <iostream>

int main() {
    int preco = 10;
    int quantidade = 3;
    std::cout << "Total: " << preco * quantidade << '\n';
    std::cout << "Itens: " << quantidade << '\n';
}

Compilação, ligação ou execução?

Um programa C++ passa por etapas (veja Como o C++ Vira Programa), e cada etapa tem o seu jeito de reclamar. Saber em qual etapa o erro aconteceu já diz metade da solução.

EtapaComo a mensagem começaO que aconteceuSeção
Compilaçãoarquivo.cpp:5:5: error: …O compilador não entendeu o código ou achou um erro de tipo. Nenhum programa é criado.Os 10 mais comuns, outros
Compilação (aviso)arquivo.cpp:2:9: warning: …O programa foi criado, mas há algo suspeito. Quase sempre é um defeito de verdade.Avisos
Ligação/usr/bin/x86_64-linux-gnu-ld.bfd: …
collect2: error: ld returned 1 exit status
Cada arquivo compilou, mas, na hora de juntar as peças, falta uma (ou sobra uma repetida).Ligação
ExecuçãoFalha de segmentação, terminate called after throwing…, AbortadoO programa foi criado e rodou, mas morreu no meio.Execução

Os 10 erros mais comuns: g++ × clang++

A primeira linha de cada mensagem, nos dois compiladores. O editor do guia mostra a coluna do clang++. Abaixo da tabela, cada um em detalhe.

#Causag++ 15clang++ 21 (editor do guia)
1Faltou o ;error: expected ‘;’ before ‘}’ token
error: expected ‘,’ or ‘;’ before ‘std’
error: expected ';' after expression
error: expected ';' at end of declaration
2Nome não declarado (ou digitado errado)error: ‘totl’ was not declared in this scope; did you mean ‘total’?error: use of undeclared identifier 'totl'; did you mean 'total'?
3Esqueceu o std::error: ‘cout’ was not declared in this scope; did you mean ‘std::cout’?
error: ‘string’ was not declared in this scope
error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
error: unknown type name 'string'; did you mean 'std::string'?
4Faltou um #includeerror: ‘setw’ is not a member of ‘std’
+ note: ‘std::setw’ is defined in header ‘<iomanip>’
error: no member named 'setw' in namespace 'std' (e às vezes uma sugestão sem sentido)
5Nome do #include erradofatal error: iostrem: Arquivo ou diretório inexistentefatal error: 'iostrem' file not found
6Valor de um tipo onde se espera outroerror: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]error: cannot initialize a variable of type 'int' with an lvalue of type 'const char[3]'
7cout << de algo que ele não sabe mostrarerror: no match for ‘operator<<’ (operand types are ‘std::ostream’ … and ‘std::vector<int>’)error: invalid operands to binary expression ('ostream' … and 'std::vector<int>')
8Número errado de argumentoserror: too few arguments to function ‘int soma(int, int)’error: no matching function for call to 'soma'
9Mudar uma constanteerror: assignment of read-only variable ‘maximo’error: cannot assign to variable 'maximo' with const-qualified type 'const int'
10Faltou fechar uma }error: expected ‘}’ at end of inputerror: expected '}'
+Função declarada, mas não definida (ligação)referência não definida para "soma(int, int)"
(em inglês: undefined reference to `soma(int, int)')
collect2: error: ld returned 1 exit status
a mesma do ld, e no fim:
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
1. expected ‘;’ before … — faltou o ponto e vírgula
#include <iostream>

int main() {
    std::cout << "Olá" << '\n'
}
$ g++ -std=c++23 -Wall -Wextra pontovirgula2.cpp -o pontovirgula2
pontovirgula2.cpp: In function ‘int main()’:
pontovirgula2.cpp:4:31: error: expected ‘;’ before ‘}’ token
    4 |     std::cout << "Olá" << '\n'
      |                               ^
      |                               ;
    5 | }
      | ~
$ clang++ -std=c++23 -Wall -Wextra pontovirgula2.cpp -o pontovirgula2
pontovirgula2.cpp:4:32: error: expected ';' after expression
    4 |     std::cout << "Olá" << '\n'
      |                               ^
      |                               ;
1 error generated.

Quando falta o ; numa declaração (int idade = 30), o g++ escreve expected ‘,’ or ‘;’ before ‘std’ (com a palavra que veio depois) e o clang++, expected ';' at end of declaration.

Como consertar: o g++ aponta o lugar onde percebeu a falta, que muitas vezes é o começo da linha seguinte. Olhe o fim da linha anterior. Aula: Sintaxe.

2. ‘x’ was not declared in this scope — nome que não existe
#include <iostream>

int main() {
    int total = 10;
    std::cout << totl << '\n';
}
$ g++ -std=c++23 -Wall -Wextra naodeclarada.cpp -o naodeclarada
naodeclarada.cpp: In function ‘int main()’:
naodeclarada.cpp:5:18: error: ‘totl’ was not declared in this scope; did you mean ‘total’?
    5 |     std::cout << totl << '\n';
      |                  ^~~~
      |                  total
naodeclarada.cpp:4:9: warning: unused variable ‘total’ [-Wunused-variable]
    4 |     int total = 10;
      |         ^~~~~
$ clang++ -std=c++23 -Wall -Wextra naodeclarada.cpp -o naodeclarada
naodeclarada.cpp:5:18: error: use of undeclared identifier 'totl'; did you mean 'total'?
    5 |     std::cout << totl << '\n';
      |                  ^~~~
      |                  total
naodeclarada.cpp:4:9: note: 'total' declared here
    4 |     int total = 10;
      |         ^
1 error generated.

O que significa: "totl não foi declarado neste escopo". As causas: nome digitado diferente (maiúsculas contam: Total ≠ total), variável criada depois da linha, ou criada dentro de outro bloco { } (veja Escopo). Sem nenhum tipo antes (idade = 30;), a mensagem é a mesma: em C++, toda variável precisa ser declarada com um tipo.

Como consertar: aceite a sugestão did you mean se ela fizer sentido, ou declare a variável antes de usar: int idade = 30;. Aula: Variáveis.

3. ‘cout’ was not declared … did you mean ‘std::cout’? — faltou o std::
$ g++ -std=c++23 -Wall -Wextra semstd.cpp -o semstd
semstd.cpp: In function ‘int main()’:
semstd.cpp:4:5: error: ‘cout’ was not declared in this scope; did you mean ‘std::cout’?
    4 |     cout << "Olá\n";
      |     ^~~~
      |     std::cout
In file included from semstd.cpp:1:
/usr/include/c++/15/iostream:65:18: note: ‘std::cout’ declared here
   65 |   extern ostream cout;          ///< Linked to standard output
      |                  ^~~~
$ clang++ -std=c++23 -Wall -Wextra semstd.cpp -o semstd
semstd.cpp:4:5: error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
    4 |     cout << "Olá\n";
      |     ^~~~
      |     std::cout
/usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/iostream:65:18: note: 'std::cout' declared here
   65 |   extern ostream cout;          ///< Linked to standard output
      |                  ^
1 error generated.

Com string nome = "Ana"; o g++ escreve error: ‘string’ was not declared in this scope e lista note: suggested alternatives: ‘std::string’; o clang++, error: unknown type name 'string'; did you mean 'std::string'?. Com endl: ‘endl’ was not declared in this scope; did you mean ‘std::endl’?.

O que significa: tudo da biblioteca padrão mora no "sobrenome" std (um namespace).

Como consertar: escreva std::cout, std::string, std::endl. Aula: Saída com cout.

4. ‘setw’ is not a member of ‘std’ — faltou um #include
$ g++ -std=c++23 -Wall -Wextra semiomanip.cpp -o semiomanip
semiomanip.cpp: In function ‘int main()’:
semiomanip.cpp:4:23: error: ‘setw’ is not a member of ‘std’
    4 |     std::cout << std::setw(5) << 42 << '\n';
      |                       ^~~~
semiomanip.cpp:2:1: note: ‘std::setw’ is defined in header ‘<iomanip>’; this is probably fixable by adding ‘#include <iomanip>’
    1 | #include <iostream>
  +++ |+#include <iomanip>
    2 |
$ clang++ -std=c++23 -Wall -Wextra semiomanip.cpp -o semiomanip
semiomanip.cpp:4:18: error: no member named 'setw' in namespace 'std'; did you mean 'getw'?
    4 |     std::cout << std::setw(5) << 42 << '\n';
      |                  ^~~~~~~~~
      |                  getw
/usr/include/stdio.h:647:12: note: 'getw' declared here
  647 | extern int getw (FILE *__stream) __nonnull ((1));
      |            ^
semiomanip.cpp:4:28: error: cannot initialize a parameter of type 'FILE *' (aka '_IO_FILE *') with an rvalue of type 'int'
    4 |     std::cout << std::setw(5) << 42 << '\n';
      |                            ^
/usr/include/stdio.h:647:24: note: passing argument to parameter '__stream' here
  647 | extern int getw (FILE *__stream) __nonnull ((1));
      |                        ^
2 errors generated.

O que significa: "setw não é membro de std": o cabeçalho que o traz não foi incluído. O g++ ainda diz qual incluir (+++ |+#include <iomanip> mostra a linha a acrescentar). O clang++ tenta adivinhar um nome parecido (getw), que não tem nada a ver: ignore a sugestão.

Outras formas do mesmo problema: sem <map>, ‘map’ is not a member of ‘std’ (clang++: no template named 'map' in namespace 'std'; did you mean 'max'?); sem <cmath>, ‘sqrt’ was not declared in this scope; sem <vector>, uma mensagem estranha: error: wrong number of template arguments (1, should be 2) (clang++: too few template arguments for class template 'vector').

Como consertar: acrescente o #include certo no topo. Cuidado: às vezes um cabeçalho traz outro "de carona" e o programa compila sem o #include (no g++ 15, std::string funcionou só com <iostream>). Não conte com isso: inclua sempre o que usa. Aula: O Pré-processador.

5. fatal error: iostrem: Arquivo ou diretório inexistente
$ g++ -std=c++23 -Wall -Wextra arquivo.cpp -o arquivo
arquivo.cpp:1:10: fatal error: iostrem: Arquivo ou diretório inexistente
    1 | #include <iostrem>
      |          ^~~~~~~~~
compilation terminated.
$ clang++ -std=c++23 -Wall -Wextra arquivo.cpp -o arquivo
arquivo.cpp:1:10: fatal error: 'iostrem' file not found
    1 | #include <iostrem>
      |          ^~~~~~~~~
1 error generated.

O que significa: o arquivo pedido no #include não existe. fatal error para a compilação na hora (compilation terminated). O pedaço "Arquivo ou diretório inexistente" vem do sistema, por isso está em português; em inglês: No such file or directory.

Como consertar: confira a grafia (iostream). Para um arquivo seu, use aspas e confira a pasta: #include "soma.h". Aula: Arquivos .h e .cpp.

6. invalid conversion from ‘const char*’ to ‘int’ — tipo errado
$ cat tipo.cpp
int main() {
    int idade = "30";
    return idade;
}
$ g++ -std=c++23 -Wall -Wextra tipo.cpp -o tipo
tipo.cpp: In function ‘int main()’:
tipo.cpp:2:17: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]
    2 |     int idade = "30";
      |                 ^~~~
      |                 |
      |                 const char*
$ clang++ -std=c++23 -Wall -Wextra tipo.cpp -o tipo
tipo.cpp:2:9: error: cannot initialize a variable of type 'int' with an lvalue of type 'const char[3]'
    2 |     int idade = "30";
      |         ^       ~~~~
1 error generated.

O que significa: "30", entre aspas, é texto (para o compilador, const char* ou const char[3]: dois caracteres mais o final invisível), e a variável é int. O C++ não converte texto em número sozinho.

Parentes: char letra = "A"; dá invalid conversion from ‘const char*’ to ‘char’ (use aspas simples: 'A'); std::string s = 5; dá conversion from ‘int’ to non-scalar type ‘std::string’ … requested (clang++: no viable conversion from 'int' to 'std::string').

Como consertar: tire as aspas (int idade = 30;) ou, se o texto vem de fora, converta com std::stoi. Aulas: Tipos de Dados, Texto ↔ Número, char.

7. no match for ‘operator<<’ — o cout não sabe mostrar isso
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v{1, 2, 3};
    std::cout << v << '\n';
}
$ g++ -std=c++23 -Wall -Wextra coutvector.cpp -o coutvector
coutvector.cpp: In function ‘int main()’:
coutvector.cpp:6:15: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘std::vector<int>’)
    6 |     std::cout << v << '\n';
      |     ~~~~~~~~~ ^~ ~
      |          |       |
      |          |       std::vector<int>
      |          std::ostream {aka std::basic_ostream<char>}
coutvector.cpp:6:15: note: there are 52 candidates
«  … mais 360 linhas de "candidate N: …", uma para cada tipo que o cout sabe mostrar …
$ clang++ -std=c++23 -Wall -Wextra coutvector.cpp -o coutvector
coutvector.cpp:6:15: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'std::vector<int>')
    6 |     std::cout << v << '\n';
      |     ~~~~~~~~~ ^  ~
«  … mais 145 linhas de "candidate … not viable" …

O que significa: "não existe << que receba um ostream e um std::vector<int>". O cout sabe mostrar números, texto e caracteres, mas não um vetor inteiro (nem uma struct sua). As 52 "candidatas" são as versões de << que existem; nenhuma serve.

Como consertar: mostre item por item com um for de intervalo, ou use std::println("{}", v); do C++23, que sabe mostrar vetores (std::format e std::print). Para uma classe sua, ensine o << a ela (Sobrecarga de Operadores).

8. too few arguments to function / no matching function for call to
$ g++ -std=c++23 -Wall -Wextra argumentos.cpp -o argumentos
argumentos.cpp: In function ‘int main()’:
argumentos.cpp:6:16: error: too few arguments to function ‘int soma(int, int)’
    6 |     return soma(2);
      |            ~~~~^~~
argumentos.cpp:1:5: note: declared here
    1 | int soma(int a, int b) {
      |     ^~~~
$ clang++ -std=c++23 -Wall -Wextra argumentos.cpp -o argumentos
argumentos.cpp:6:12: error: no matching function for call to 'soma'
    6 |     return soma(2);
      |            ^~~~
argumentos.cpp:1:5: note: candidate function not viable: requires 2 arguments, but 1 was provided
    1 | int soma(int a, int b) {
      |     ^    ~~~~~~~~~~~~
1 error generated.

O que significa: "argumentos de menos para a função soma(int, int)": ela pede dois, você deu um. Com argumentos demais, too many arguments. Quando há várias versões da função (sobrecarga) e nenhuma serve, o g++ também diz no matching function for call to ‘…’ e lista as candidatas.

Como consertar: confira a assinatura que a nota declared here mostra e passe os argumentos na quantidade e nos tipos certos. Aulas: Parâmetros e Argumentos, Valores Padrão.

9. assignment of read-only variable — mudar uma constante
$ g++ -std=c++23 -Wall -Wextra const.cpp -o const
const.cpp: In function ‘int main()’:
const.cpp:3:12: error: assignment of read-only variable ‘maximo’
    3 |     maximo = 20;
      |     ~~~~~~~^~~~
$ clang++ -std=c++23 -Wall -Wextra const.cpp -o const
const.cpp:3:12: error: cannot assign to variable 'maximo' with const-qualified type 'const int'
    3 |     maximo = 20;
      |     ~~~~~~ ^
const.cpp:2:15: note: variable 'maximo' declared const here
    2 |     const int maximo = 10;
      |     ~~~~~~~~~~^~~~~~~~~~~
1 error generated.

O que significa: "atribuição a variável somente leitura": maximo foi declarada const. O compilador está fazendo o trabalho dele: proteger um valor que você mesmo disse que não muda.

Como consertar: se o valor precisa mudar, tire o const; se não, não mude. Aula: Constantes.

10. expected ‘}’ at end of input — faltou fechar uma chave
$ cat chave.cpp
#include <iostream>

int main() {
    if (true) {
        std::cout << "oi\n";
}
$ g++ -std=c++23 -Wall -Wextra chave.cpp -o chave
chave.cpp: In function ‘int main()’:
chave.cpp:6:2: error: expected ‘}’ at end of input
    6 | }
      |  ^
chave.cpp:3:12: note: to match this ‘{’
    3 | int main() {
      |            ^
$ clang++ -std=c++23 -Wall -Wextra chave.cpp -o chave
chave.cpp:6:2: error: expected '}'
    6 | }
      |  ^
chave.cpp:3:12: note: to match this '{'
    3 | int main() {
      |            ^
1 error generated.

O que significa: o arquivo acabou ("end of input") com uma { ainda aberta. A nota aponta a chave que ficou sem par, mas atenção: o compilador casa cada } com a { aberta mais recente, então a chave que de fato ficou sem fechar (aqui, a do if) pode ser outra.

O contrário, uma } sobrando, dá expected declaration before ‘}’ token (clang++: extraneous closing brace ('}')).

Como consertar: mantenha a indentação certinha (o editor ajuda) e confira bloco por bloco. Aula: Sintaxe.


Outros erros de compilação

A primeira linha da mensagem do g++ 15 (e, quando muda muito, a do clang++), a causa e a correção. Os nomes (x, Aluno…) são dos exemplos; no seu código, serão outros.

Sintaxe e texto

MensagemCausa típicaCorreçãoAula
expected primary-expression before ‘;’ token
clang++: expected expression
Faltou um pedaço da conta: int x = 5 * ;. Também aparece em cascata depois de outro erro.Complete a expressão.Aritméticos
‘x’ does not name a type
clang++: a type specifier is required for all declarations
Uma instrução (x = 5;) fora de qualquer função. Fora de funções só cabem declarações.Mova a instrução para dentro do main ou de outra função.Funções
‘::main’ must return ‘int’void main(), comum em livros antigos.Use int main().Olá, Mundo
redeclaration of ‘int x’
clang++: redefinition of 'x'
Duas variáveis com o mesmo nome no mesmo bloco.Para mudar o valor, tire o tipo: x = 2;.Variáveis
‘else’ without a previous ‘if’
clang++: expected expression
Um ; logo depois do if (…), ou um else sobrando.Tire o ;: if (x > 0) {.if e else
extended character “ is not valid in an identifier
clang++: unexpected character <U+201C>
Aspas "curvas" (“Olá”), coladas de um site, do Word ou de um PDF.Troque pelas aspas retas do teclado: "Olá".Strings
missing terminating " characterAbriu aspas e não fechou: "Olá << '\n';. Vem junto com outros erros em cascata.Feche as aspas na mesma linha.Strings
invalid operands of types ‘const char [7]’ and ‘const char [4]’ to binary ‘operator+’Somar dois textos entre aspas: "Olá, " + "Ana".Faça um deles virar std::string: std::string("Olá, ") + "Ana", ou junte numa só: "Olá, Ana".Juntar Strings
no match for ‘operator==’ (operand types are ‘std::string’ … and ‘char’)Comparar texto com um caractere: nome == 'A'.Use aspas duplas (nome == "A") ou compare um caractere (nome[0] == 'A').Acessar Caracteres
narrowing conversion of ‘3.7000000000000002e+0’ from ‘double’ to ‘int’ [-Wnarrowing]int x{3.7};: as chaves não deixam perder informação.Use o tipo certo (double x{3.7};) ou converta de propósito: static_cast<int>(3.7).Conversão de Tipos

Funções, tipos e referências

MensagemCausa típicaCorreçãoAula
void value not ignored as it ought to be
clang++: cannot initialize a variable of type 'int' with an rvalue of type 'void'
Guardar o resultado de uma função void: int x = ola();.Faça a função devolver um valor, ou só chame: ola();.Retorno
return-statement with no value, in function returning ‘int’ [-fpermissive]
clang++: non-void function 'pega' should return a value
return; sozinho numa função que promete um int.return 0; (ou o valor certo).Retorno
lvalue required as left operand of assignment
clang++: expression is not assignable
Do lado esquerdo do = há uma conta, não uma variável: if (x + 1 = 2). Quase sempre era ==.Para comparar, use ==.Comparação
cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
clang++: no matching function for call to 'dobra'
Passar um valor solto (dobra(5)) para um parâmetro int&, que precisa de uma variável para mudar.Passe uma variável, ou use const int& se a função não muda o valor.Por Referência
call of overloaded ‘f(long int)’ is ambiguous
clang++: call to 'f' is ambiguous
Duas versões da função servem igualmente bem.Passe o tipo exato (f(5), f(5.0)) ou converta.Sobrecarga
switch quantity not an integerswitch com std::string.Use if/else if, ou um enum.switch
jump to case label + note: crosses initialization of ‘int x’Uma variável criada dentro de um case sem chaves.Ponha o case entre chaves: case 1: { int x = 5; … }.switch
‘println’ is not a member of ‘std’ + note: ‘std::println’ is only available from C++23 onwardsCompilou sem -std=c++23: o g++ 15 usa C++17 se você não pedir outro.Use o comando padrão: g++ -std=c++23 ….Compilar
call to consteval function ‘std::basic_format_string<…>("{} tem {} anos")’ is not a constant expressionstd::format/std::println com mais {} do que valores. O erro é pego na compilação.Um valor para cada {}.std::format

Classes, ponteiros e containers

MensagemCausa típicaCorreçãoAula
‘class std::vector<int>’ has no member named ‘length’
clang++: no member named 'length' in 'std::vector<int>'
Método que não existe nesse tipo (no vetor, o tamanho é size()).Confira o nome do método na referência.Containers
request for member ‘size’ in ‘p’, which is of pointer type … (maybe you meant to use ‘->’ ?)Usar . num ponteiro.p->size().Ponteiros
‘double Conta::saldo’ is private within this context
clang++: 'saldo' is a private member of 'Conta'
Mexer num membro private de fora da classe (numa class, tudo é privado até um public:).Use um método público, ou reveja o public:.public e private
no matching function for call to ‘Aluno::Aluno()’
clang++: no matching constructor for initialization of 'Aluno'
Aluno a; sem argumentos, mas a classe só tem construtor que pede um nome.Passe os argumentos (Aluno a{"Ana"};) ou crie um construtor padrão.Construtores
passing ‘const Aluno’ as ‘this’ argument discards qualifiers [-fpermissive]
clang++: 'this' argument to member function 'nome' has type 'const Aluno', but function is not marked const
Chamar um método não-const num objeto const (por exemplo, recebido por const Aluno&).Marque o método como const: std::string nome() const.Métodos const
cannot declare variable ‘f’ to be of abstract type ‘Forma’
clang++: variable type 'Forma' is an abstract class
Criar um objeto de uma classe com método virtual puro (= 0).Crie um objeto de uma classe filha que implemente o método.Classes Abstratas
‘void Gato::som()’ marked ‘override’, but does not overrideA assinatura não bate com a da classe mãe (aqui faltou o const).Copie a assinatura exata: void som() const override.Polimorfismo
use of deleted function ‘std::unique_ptr<…>::unique_ptr(const std::unique_ptr<…>&)’
clang++: call to deleted constructor of …
Copiar um std::unique_ptr (auto b = a;): ele tem um dono só.Transfira com auto b = std::move(a);, ou use std::shared_ptr.Ponteiros Inteligentes
wrong number of template arguments (1, should be 2)Usou std::vector<int> sem #include <vector>.Inclua <vector>.std::vector

Mensagens gigantes (templates e concepts)

Quando o erro acontece dentro de um template da biblioteca (std::sort, std::vector, cout <<…), o compilador mostra o caminho inteiro por dentro dela. O cout << v do erro 7 rende 378 linhas no g++. Não se assuste; procure três coisas:

  1. a primeira linha com error:;
  2. a linha required from here que aponta um arquivo seu (é a sua linha que causou tudo);
  3. com concepts, a linha the expression ‘…’ evaluated to ‘false’ ou required for the satisfaction of ‘…’, que diz qual exigência não foi cumprida.

Um filtro ajuda. Aqui, o std::sort numa std::list (veja a armadilha em Algoritmos), de 29 linhas reduzidas a 2:

$ g++ -std=c++23 -Wall -Wextra lista.cpp -o lista 2>&1 | grep -E "error|required from here"
lista.cpp:6:14:   required from here
/usr/include/c++/15/bits/stl_algo.h:1907:50: error: no match for ‘operator-’ (operand types are ‘std::_List_iterator<int>’ and ‘std::_List_iterator<int>’)

(O 2>&1 manda as mensagens, que saem na saída de erro, para o grep.)

Com concepts C++20, a mensagem fica mais legível. Uma função que só aceita inteiros, chamada com 2.5:

#include <concepts>

template <std::integral T>
T dobro(T x) { return 2 * x; }

int main() {
    dobro(2.5);
}
$ g++ -std=c++23 -Wall -Wextra concept.cpp -o concept
concept.cpp: In function ‘int main()’:
concept.cpp:7:10: error: no matching function for call to ‘dobro(double)’
    7 |     dobro(2.5);
      |     ~~~~~^~~~~
concept.cpp:7:10: note: there is 1 candidate
concept.cpp:4:3: note: candidate 1: ‘template<class T>  requires  integral<T> T dobro(T)’
    4 | T dobro(T x) { return 2 * x; }
      |   ^~~~~
concept.cpp:4:3: note: template argument deduction/substitution failed:
concept.cpp:4:3: note: constraints not satisfied
In file included from concept.cpp:1:
/usr/include/c++/15/concepts: In substitution of ‘template<class T>  requires  integral<T> T dobro(T) [with T = double]’:
concept.cpp:7:10:   required from here
    7 |     dobro(2.5);
      |     ~~~~~^~~~~
/usr/include/c++/15/concepts:109:13:   required for the satisfaction of ‘integral<T>’ [with T = double]
/usr/include/c++/15/concepts:109:24: note: the expression ‘is_integral_v<_Tp> [with _Tp = double]’ evaluated to ‘false’
  109 |     concept integral = is_integral_v<_Tp>;
      |                        ^~~~~~~~~~~~~~~~~~
$ clang++ -std=c++23 -Wall -Wextra concept.cpp -o concept
concept.cpp:7:5: error: no matching function for call to 'dobro'
    7 |     dobro(2.5);
      |     ^~~~~
concept.cpp:4:3: note: candidate template ignored: constraints not satisfied [with T = double]
    4 | T dobro(T x) { return 2 * x; }
      |   ^
concept.cpp:3:11: note: because 'double' does not satisfy 'integral'
    3 | template <std::integral T>
      |           ^
/usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/concepts:109:24: note: because 'is_integral_v<double>' evaluated to false
  109 |     concept integral = is_integral_v<_Tp>;
      |                        ^
1 error generated.

Leitura: "não há dobro(double); a única candidata exige integral<T>, e com T = double isso deu false". O clang++ diz direto: 'double' does not satisfy 'integral'. Aulas: Templates de Função, Concepts.


Avisos (-Wall -Wextra)

Um aviso (warning) não impede o programa de ser criado, mas quase sempre aponta um defeito. Compile sempre com -Wall -Wextra e deixe a saída limpa. O nome entre colchetes é a opção que liga o aviso. Veja a aula Avisos.

Aviso do g++ 15clang++ 21Causa e correção
unused variable ‘x’ [-Wunused-variable]unused variable 'x'Criou e nunca usou. Apague, ou use. Aula: Variáveis.
unused parameter ‘b’ [-Wunused-parameter]unused parameter 'b'Parâmetro que a função ignora. Se for de propósito, tire o nome: int f(int a, int). Aula: Parâmetros.
variable ‘x’ set but not used [-Wunused-but-set-variable]igualRecebe valores, mas ninguém lê. Sobra de código antigo.
comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<int>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]comparison of integers of different signs: 'int' and 'size_type' (aka 'unsigned long')for (int i = 0; i < v.size(); i++): size() é sem sinal. Use std::size_t i ou, melhor, um for de intervalo. Aula: Inteiros.
suggest parentheses around assignment used as truth value [-Wparentheses]using the result of an assignment as a condition without parenthesesif (x = 5) atribui 5 e é sempre verdadeiro. Quase sempre era ==. Aula: Comparação.
‘soma’ is used uninitialized [-Wuninitialized]variable 'soma' is uninitialized when used here + sugestão = 0int soma; soma += 10;: o valor inicial é lixo. Inicialize: int soma = 0;. Aula: Comportamento Indefinido.
no return statement in function returning non-void [-Wreturn-type]non-void function does not return a valueA função promete um valor e acaba sem return. Compila, mas o resultado é indefinido. Aula: Retorno.
address of local variable ‘x’ returned [-Wreturn-local-addr]address of stack memory associated with local variable 'x' returnedDevolver &x de uma variável que morre no fim da função. Devolva o valor. Aula: Como a Memória Funciona.
this statement may fall through [-Wimplicit-fallthrough=](o clang++ não avisa com -Wall -Wextra)Um case sem break "cai" no próximo. Ponha o break; (ou [[fallthrough]]; se for de propósito). Aula: switch.
suggest braces around empty body in an ‘if’ statement [-Wempty-body]if statement has empty bodyif (x > 0);: o ; é o corpo inteiro do if. Tire o ;. Aula: if e else.
this ‘if’ clause does not guard... [-Wmisleading-indentation]misleading indentation; statement is not part of the previous 'if'Duas linhas recuadas debaixo de um if sem chaves: só a primeira é dele. Use sempre { }.
division by zero [-Wdiv-by-zero]division by zero is undefinedx / 0 escrito no código. Ao rodar, o programa morre (veja abaixo).
integer overflow in expression of type ‘int’ results in ‘-2147483648’ [-Woverflow]overflow in expression; result is -2'147'483'648 with type 'int'A conta passa do maior int. Use long long. Aula: Inteiros.
comparison of unsigned expression in ‘>= 0’ is always true [-Wtype-limits](não avisa)for (unsigned i = 10; i >= 0; i--) nunca termina: um unsigned nunca é negativo. Use int.
narrowing conversion of ‘preco’ from ‘double’ to ‘int’ [-Wnarrowing]erro: type 'double' cannot be narrowed to 'int' in initializer listint x{preco}; com uma variável double: o g++ só avisa, o clang++ recusa. Use static_cast<int>(preco). Aula: Conversão.
infinite recursion detected [-Winfinite-recursion]—Função que chama a si mesma sem caso de parada. Aula: Recursão.
ignoring return value of ‘…std::remove…’, declared with attribute ‘nodiscard’ [-Wunused-result]ignoring return value of function declared with 'nodiscard' attributeJogou fora um resultado importante. Veja Algoritmos.
deleting object of polymorphic class type ‘Base’ which has non-virtual destructor might cause undefined behavior [-Wdelete-non-virtual-dtor]delete called on non-final 'Base' that has virtual functions but non-virtual destructorClasse base com métodos virtual precisa de virtual ~Base() = default;. Aula: Polimorfismo.
‘virtual void Animal::som() const’ was hidden [-Woverloaded-virtual=]—A classe filha criou um método com o mesmo nome e outra assinatura, escondendo o da mãe.

Missão: o programa funciona, mas o compilador dá três avisos. Elimine todos (sem apagar a mensagem de saída) até a caixa compilar sem nenhum aviso e mostrar soma: 24.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> notas{7, 9, 8};
    int soma = 0;
    int maior = 0;
    for (int i = 0; i < notas.size(); i++) {
        soma += notas[i];
    }
    if (soma = 24) {
        std::cout << "soma: " << soma << '\n';
    }
}
#include <iostream>
#include <vector>

int main() {
    std::vector<int> notas{7, 9, 8};
    int soma = 0;
    for (std::size_t i = 0; i < notas.size(); i++) {
        soma += notas[i];
    }
    if (soma == 24) {
        std::cout << "soma: " << soma << '\n';
    }
}

Erros de ligação (ld)

Depois de compilar cada .cpp, o g++ chama o ligador (ld, de linker), que junta as peças num programa só. Os erros dele não têm número de linha: em vez de arquivo.cpp:5:5:, aparecem nomes de arquivos temporários (/tmp/ccsEstGP.o) e a frase collect2: error: ld returned 1 exit status ("o ld terminou com erro"). Na máquina da Ana, o ld fala português; com o sistema em inglês (LANG=C), a mesma mensagem fica como na segunda parte de cada exemplo. Aulas: Compilar Vários Arquivos e Arquivos .h e .cpp.

referência não definida para / undefined reference to

O main.cpp inclui soma.h (que só declara int soma(int a, int b);), mas a Ana compilou só o main.cpp, esquecendo o soma.cpp, onde a função é definida:

$ g++ -std=c++23 -Wall -Wextra main.cpp -o main
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccsEstGP.o: na função "main":
main.cpp:(.text+0x13): referência não definida para "soma(int, int)"
collect2: error: ld returned 1 exit status
$ LANG=C g++ -std=c++23 -Wall -Wextra main.cpp -o main
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccTr6gcB.o: in function `main':
main.cpp:(.text+0x13): undefined reference to `soma(int, int)'
collect2: error: ld returned 1 exit status
$ clang++ -std=c++23 -Wall -Wextra main.cpp -o main
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/main-e08580.o: na função "main":
main.cpp:(.text+0xf): referência não definida para "soma(int, int)"
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
$ g++ -std=c++23 -Wall -Wextra main.cpp soma.cpp -o main
$ ./main
5

No editor do guia, o ligador é outro (wasm-ld) e a mesma falha aparece como wasm-ld: error: /tmp/main-62bf3f.o: undefined symbol: soma(int, int) ("símbolo não definido").

O que significa: "dentro da função main, há uma chamada a soma(int, int), mas ninguém a definiu". O compilador aceitou a chamada porque viu a declaração no .h; o ligador não achou o corpo da função.

Causas e consertos:

  • esqueceu um .cpp no comando: g++ … main.cpp soma.cpp -o main;
  • o nome ou os parâmetros da definição não batem com a declaração (int Soma(int a, int b) no .cpp, int soma(int, int) no .h: maiúscula conta);
  • a função foi declarada e nunca escrita;
  • uma biblioteca externa não foi ligada (falta um -lnome; veja Usar Bibliotecas Externas).

Um arquivo sem main dá a mesma família de erro: (.text+0x1b): referência não definida para "main" (em inglês, undefined reference to `main'), vinda de Scrt1.o: na função "_start", o código que o sistema roda antes do seu main.

múltiplas definições de / multiple definition of

O cabeçalho config.h define uma variável (int total = 0;) e é incluído em a.cpp e em b.cpp. Cada arquivo ganha a sua cópia, e o ligador não sabe com qual ficar:

$ g++ -std=c++23 -Wall -Wextra a.cpp b.cpp -o prog
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccfu3U3T.o:(.bss+0x0): múltiplas definições de "total"; /tmp/cciF57P8.o:(.bss+0x0): definido primeiro aqui
collect2: error: ld returned 1 exit status
$ LANG=C g++ -std=c++23 -Wall -Wextra a.cpp b.cpp -o prog
/usr/bin/x86_64-linux-gnu-ld.bfd: /tmp/ccV3ztVv.o:(.bss+0x0): multiple definition of `total'; /tmp/ccw6qlvg.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

O #pragma once não resolve: ele evita incluir o mesmo .h duas vezes no mesmo .cpp, não em dois .cpp diferentes.

Como consertar: no .h, use inline int total = 0; C++17 (uma variável compartilhada, permitida em vários arquivos), ou declare com extern int total; no .h e defina int total = 0; num .cpp só. Para funções escritas no .h, a mesma regra: marque-as inline.

Missão: o programa tem três arquivos (abas). Clique em Rodar: a compilação passa, mas a ligação falha, porque a função chamada no main.cpp não foi definida com o mesmo nome. Conserte o soma.cpp até o programa mostrar 5.

#include <iostream>
#include "soma.h"

int main() {
    std::cout << soma(2, 3) << '\n';
}
#pragma once

int soma(int a, int b);
#include "soma.h"

int Soma(int a, int b) {
    return a + b;
}
#include "soma.h"

int soma(int a, int b) {
    return a + b;
}

Erros de execução

O programa compilou, ligou, começou a rodar… e morreu. Quem escreve a mensagem final é o terminal (o bash), que na máquina da Ana fala português; a versão em inglês está ao lado. "Imagem do núcleo gravada" (core dumped) quer dizer que o sistema pode ter salvado uma "foto" da memória do programa para análise (veja Depurar com o GDB). As saídas abaixo foram feitas num terminal de verdade.

Falha de segmentação / Segmentation fault — código 139
#include <iostream>

int main() {
    int* p = nullptr;
    std::cout << "antes\n";
    std::cout << *p << '\n';
}
$ g++ -std=c++23 -Wall -Wextra nulo.cpp -o nulo
$ ./nulo
antes
Falha de segmentação     (imagem do núcleo gravada) ./nulo
$ echo $?
139

Em inglês: Segmentation fault (core dumped) ./nulo.

O que significa: o programa tentou ler ou escrever numa parte da memória que não é dele, e o sistema o matou com o sinal SIGSEGV. Causas típicas: usar um ponteiro nulo (*p com p = nullptr), um ponteiro para algo que já foi apagado, um índice muito fora do array, ou uma recursão sem fim, que estoura a pilha (a conta(n + 1) sem caso de parada deu a mesma mensagem e o mesmo 139).

Como consertar: confira ponteiros antes de usar (if (p != nullptr)), prefira std::vector e ponteiros inteligentes, e use o gdb ou os sanitizers para achar a linha. Aulas: Ponteiros, nullptr.

Exceção de ponto flutuante / Floating point exception — código 136
#include <iostream>

int main() {
    int total = 10, pessoas = 0;
    std::cin >> pessoas;
    std::cout << total / pessoas << '\n';
}
$ echo 0 | ./divisao
Exceção de ponto flutuante (imagem do núcleo gravada) echo 0 | ./divisao
$ echo $?
136

Em inglês: Floating point exception (core dumped) echo 0 | ./divisao.

O que significa: apesar do nome, é uma divisão inteira por zero (ou o resto % por zero). O processador recusa a conta e o sistema mata o programa com o sinal SIGFPE. Com double, dividir por zero não mata o programa: dá inf ou nan.

Como consertar: confira o divisor antes: if (pessoas == 0) { … }. Aulas: Aritméticos, Validar a Entrada.

terminate called after throwing an instance of … + Abortado — código 134
#include <iostream>
#include <vector>

int main() {
    std::vector<int> notas{7, 9, 8};
    std::cout << notas.at(10) << '\n';
}
$ ./at
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 10) >= this->size() (which is 3)
Abortado                   (imagem do núcleo gravada) ./at
$ echo $?
134

Em inglês, a última linha fica Aborted (core dumped) ./at.

O que significa: uma exceção foi lançada e ninguém a capturou com try/catch. O C++ então chama std::terminate, que mostra o tipo da exceção (std::out_of_range) e a mensagem dela (what():), e aborta o programa com o sinal SIGABRT. Aqui: "índice 10 ≥ tamanho 3".

As que mais aparecem (todas reais, todas com código 134):

Tipo e what()Quem lançaAula
'std::out_of_range'
what(): vector::_M_range_check: __n (which is 10) >= this->size() (which is 3)
v.at(i) ou s.at(i) com índice fora do tamanho.std::vector
'std::invalid_argument'
what(): stoi
std::stoi("trinta"): o texto não começa com um número.Texto ↔ Número
'std::runtime_error'
what(): saldo insuficiente
O seu próprio throw std::runtime_error("saldo insuficiente");.Exceções
'int' (sem what())throw 42;: dá para lançar qualquer coisa, mas prefira as classes de <stdexcept>.Exceções
'std::bad_alloc'
what(): std::bad_alloc
Faltou memória (aqui, um std::vector<int> de 5 bilhões de itens com a memória limitada por ulimit -v).new e delete
'std::bad_optional_access'
what(): bad optional access
x.value() num std::optional vazio.optional e variant

Como consertar: evite a causa (confira o índice, valide o texto) ou capture a exceção onde você sabe o que fazer: try { … } catch (const std::exception& e) { std::cout << e.what(); }.

Assertion '__n < this->size()' failed. — índice fora com [ ]
$ cat colchete.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<int> notas{7, 9, 8};
    std::cout << notas[10] << '\n';
}
$ g++ -std=c++23 -Wall -Wextra colchete.cpp -o colchete
$ ./colchete
/usr/include/c++/15/bits/stl_vector.h:1263: constexpr std::vector< <template-parameter-1-1>, <template-parameter-1-2> >::reference std::vector< <template-parameter-1-1>, <template-parameter-1-2> >::operator[](size_type) [with _Tp = int; _Alloc = std::allocator<int>; reference = int&; size_type = long unsigned int]: Assertion '__n < this->size()' failed.
Abortado                   (imagem do núcleo gravada) ./colchete
$ g++ -std=c++23 -Wall -Wextra -O2 colchete.cpp -o colchete 2>/dev/null
$ ./colchete
0

O que significa: o [ ] do vetor não confere o índice, ao contrário do .at(). Mas a biblioteca do g++ 15, quando você compila sem otimização (sem -O2), liga umas conferências extras ("asserções") que pegam o erro e abortam (código 134). Com -O2, as conferências somem e o programa simplesmente lê lixo da memória e mostra 0 (ou qualquer outra coisa): é comportamento indefinido.

Como consertar: confira o índice (i < notas.size()), use for de intervalo, ou .at() quando o índice vem de fora.

free(): double free detected in tcache 2 — apagou duas vezes
$ cat doublefree.cpp
int main() {
    int* p = new int(5);
    delete p;
    delete p;
}
$ ./doublefree
free(): double free detected in tcache 2
Abortado                   (imagem do núcleo gravada) ./doublefree
$ echo $?
134

O que significa: o mesmo bloco de memória foi devolvido duas vezes. A biblioteca C percebeu e abortou. (tcache é o nome de uma "gaveta" interna do gerenciador de memória.) Nem sempre o erro é pego: às vezes o programa continua e falha bem depois, num lugar sem relação.

Como consertar: não use new/delete à mão: std::unique_ptr, std::vector e std::string liberam a memória sozinhos, uma vez só. Aulas: new e delete, Ponteiros Inteligentes, RAII.

Códigos de saída e sinais

Depois que o programa termina, echo $? mostra o código de saída. Quando o sistema mata o programa com um sinal, o código é 128 + o número do sinal. Os nomes dos sinais vêm do comando kill -l:

$ kill -l 6 8 9 11
ABRT
FPE
KILL
SEGV
CódigoSinalMensagem do terminal (pt / en)Causas típicas
0—nenhumaDeu tudo certo (o main terminou ou fez return 0).
1 (ou outro pequeno)—nenhumaO próprio programa escolheu: return 1;. Também é o código de um relatório do AddressSanitizer e do g++ quando a compilação falha.
124—nenhumaO comando timeout parou o programa porque o tempo acabou (um laço infinito, por exemplo).
1346, SIGABRTAbortado / AbortedExceção não capturada (terminate called…), double free, asserção que falhou, std::abort().
1368, SIGFPEExceção de ponto flutuante / Floating point exceptionDivisão inteira (ou %) por zero.
1379, SIGKILLMorto / KilledMorto à força: kill -9, timeout -s KILL, ou o sistema sem memória.
13911, SIGSEGVFalha de segmentação / Segmentation faultPonteiro nulo ou inválido, índice muito fora, recursão infinita.

Relatórios dos sanitizers (resumidos)

Os sanitizers são "fiscais" que o compilador põe dentro do programa para pegar erros de memória e comportamento indefinido na linha exata, mesmo quando o programa parece funcionar. Compile com -g -fsanitize=address,undefined. Aula completa: Sanitizers.

Um exemplo inteiro: o laço vai até i <= 3 num array de 3 itens criado com new.

#include <iostream>

int main() {
    int* notas = new int[3]{7, 9, 8};
    int soma = 0;
    for (int i = 0; i <= 3; i++) {
        soma += notas[i];
    }
    std::cout << soma << '\n';
    delete[] notas;
}
$ g++ -std=c++23 -Wall -Wextra -g -fsanitize=address,undefined heapnew.cpp -o heapnew && ./heapnew
=================================================================
==534580==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x73adb6be001c at pc 0x624669b21612 bp 0x7fff3740ad40 sp 0x7fff3740ad30
READ of size 4 at 0x73adb6be001c thread T0
    #0 0x624669b21611 in main /home/ana/erros/run/heapnew.cpp:7
    #1 0x778db782a600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59
    #2 0x778db782a717 in __libc_start_main_impl ../csu/libc-start.c:360
    #3 0x624669b21264 in _start (/home/ana/erros/run/heapnew+0x2264) (BuildId: 6e911907011ca067d2d483d8ef96462400e25fcf)

0x73adb6be001c is located 0 bytes after 12-byte region [0x73adb6be0010,0x73adb6be001c)
allocated by thread T0 here:
    #0 0x778db892c8cf in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:111
    #1 0x624669b21345 in main /home/ana/erros/run/heapnew.cpp:4
«  … (#2 a #4: as mesmas linhas de inicialização de cima) …

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ana/erros/run/heapnew.cpp:7 in main
Shadow bytes around the buggy address:
«  … 30 linhas de "bytes-sombra" (o mapa interno da memória): pode pular …
==534580==ABORTING
$ echo $?
1

Como ler: ERROR: AddressSanitizer: heap-buffer-overflow é o tipo do erro; READ of size 4, "leitura de 4 bytes" (um int); #0 … in main …/heapnew.cpp:7, a linha culpada; 0 bytes after 12-byte region, "logo depois de um bloco de 12 bytes" (3 ints); allocated by thread T0 here: … heapnew.cpp:4, onde o bloco foi criado. A linha SUMMARY resume tudo. O número ==534580== é o número do processo.

Linha principal do relatório (real)O que aconteceu
ERROR: AddressSanitizer: heap-buffer-overflow on address …Leu ou escreveu além do fim (ou antes do começo) de um bloco criado com new (ou dentro de um vector, string…).
ERROR: AddressSanitizer: stack-buffer-overflow on address …
[32, 44) 'a' (line 4) <== Memory access at offset 44 overflows this variable
O mesmo, num array local (int a[3] lido em a[3]). O relatório até diz qual variável.
ERROR: AddressSanitizer: heap-use-after-free on address …
com freed by thread T0 here: e previously allocated by thread T0 here:
Usou memória depois do delete. O relatório mostra três linhas: onde usou, onde apagou, onde criou.
ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).
Vazamento: um new int[10] (40 bytes) nunca foi apagado. Aparece no fim do programa.
overflow.cpp:6:7: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'(UndefinedBehaviorSanitizer) A conta passou do maior int. O programa continua e mostra -2147483648. Aula: Inteiros.
pilhaarray.cpp:6:21: runtime error: index 3 out of bounds for type 'int [3]'(UBSan) Índice fora de um array comum, avisado antes mesmo do AddressSanitizer.
E no editor do guia?

O editor compila com o Clang e roda o programa como WebAssembly, dentro do navegador. Os erros de compilação são os da coluna do clang++. Os de ligação e de execução não vêm do ld nem do bash do Linux, e a memória do WebAssembly funciona de outro jeito, então o resultado muda. Os mesmos programas desta página, rodados no editor:

ProgramaNo terminal (g++)No editor do guia
função sem definiçãoundefined reference to `soma(int, int)'wasm-ld: error: /tmp/main-62bf3f.o: undefined symbol: soma(int, int)
at.cpp (exceção não capturada)terminate called after throwing an instance of 'std::out_of_range', código 134libc++abi: terminating due to uncaught exception of type std::out_of_range: vector, código 134
divisao.cpp (divisão por zero)Exceção de ponto flutuante, código 136sem mensagem, código 136
nulo.cpp (*p com p = nullptr)Falha de segmentação, código 139não trava: mostra antes e 0, código 0
colchete.cpp, doublefree.cppabortam (código 134)não acusam nada: mostram 0 ou nada, código 0

Repare nas duas últimas linhas: o comportamento indefinido pode parecer funcionar. Um programa que "deu certo" no editor ainda pode ter um erro de memória; para caçá-los, compile no seu terminal com os sanitizers (Instalar no Linux). Mais sobre o editor em O Editor do Guia.


Exercícios

1. A mensagem é main.cpp:(.text+0x13): undefined reference to `soma(int, int)' seguida de collect2: error: ld returned 1 exit status. Em que etapa está o problema?

2. Um programa morre e echo $? mostra 136. Qual é a causa mais provável?

3. O g++ mostrou quatro erros. O primeiro é expected ‘,’ or ‘;’ before ‘int’ na linha 5. Qual é a melhor atitude?

4. Qual cabeçalho?

O g++ disse ‘setw’ is not a member of ‘std’. Complete a linha que resolve:

#include <>

5. 128 + sinal

O sinal SIGSEGV é o número 11. Que código de saída aparece em echo $? depois de uma "Falha de segmentação"?


Resumo

  • Leia arquivo:linha:coluna: error: texto, conserte o primeiro erro e compile de novo: os outros costumam ser cascata.
  • error impede o programa; warning deixa criar, mas aponta defeito; note explica a mensagem anterior. Compile com -Wall -Wextra e zere os avisos.
  • O editor do guia usa o Clang: as palavras mudam (was not declared × use of undeclared identifier), o sentido é o mesmo.
  • Erro de ligação (undefined reference, multiple definition, ld returned 1 exit status): falta ou sobra uma peça entre os arquivos.
  • Erros de execução: 139 = Segmentation fault, 136 = Floating point exception, 134 = Aborted (exceção não capturada, double free, asserção).
  • Para achar a linha de um erro de memória, use -g -fsanitize=address,undefined e leia o SUMMARY.