Introdução
Muitas vezes ao rodar algum programa esbarramos em mensagens que indicam que o usuário fez algo diferente do que era esperado ou que o programa, por alguma razão, encontrou uma situação indesejada ou inesperada. Dependendo da natureza do que causou essas mensagens, podemos ter o que chamamos de erros ou de exceções.
Diferenciando Erros de Exceções
Em computação os erros geralmente são situações graves, imprevisíveis, das quais um programa não consegue se recuperar porque não podem ser tratadas por código, causando uma interrupção na execução, que geralmente exige a reinicialização do programa.
Já as exceções são erros que podem ser previstos e antecipados pelo desenvolvedor, sendo consequentemente tratados por código, de maneira que o programa possa continuar a ser executado, sem causar interrupção.
São exemplos de erros os estouros de memória, estouros de pilha, falhas de hardware, entre outros. Já as exceções podem ser decorrentes de erros de cálculo, como divisão por zero ou uma raiz quadrada de número negativo, erro na entrada de dados, erros de lógica de programação, etc.
O termo Bug utilizado genericamente para problemas em software pode ser tanto relacionado a erro como exceções. Sendo que, na maioria das vezes, os bugs são decorrentes de falhas nas etapas de testes durante o ciclo de desenvolvimento de uma aplicação.
Tratando exceções em C e C++
A linguagem C não dispõe exatamente de um tratamento de exceções. O que ela permite é simular um tratamento com o uso das funções setjmp() e longjmp(), que na realidade ajustam um "pulo" em partes do código. Já a linguagem C++, assim como as Java, Python e PHP, possui dois blocos de instruções conhecidos como Try e Catch que permitem um verdadeiro tratamento de exceções.
Nesses blocos, a palavra try significa tentar e no nosso caso é o bloco de instruções que o programa "tenta" executar normalmente. Já o catch significa pegar, e é o bloco que deverá ser executado se o programa "pegar" uma exceção.
No bloco try temos ainda a declaração throw que permite passar um código de erro personalizado ou outra informação como o valor de uma variável para o catch tratar. Assim, a estrutura do try /catch costuma ser algo assim:
Vejamos um exemplo. Digamos que eu tenho um programa que pede a idade de uma pessoa e precisa validar essa idade para alguma operação. Pode ser que pessoa digite algo inválido na idade, por exemplo, ao invés de digitar o número 18 ela digita a palavra dezoito. Assim temos:
- #include <iostream>
- using namespace std;
- int main() {
- try {
- int idade;
- cout << "Digite sua idade: ";
- cin>>idade;
- if (idade >= 18) {
- cout << "Você pode dirigir.\n";
- }
- else if (idade<18 && idade>0){
- cout << "Você não pode dirigir\n";
- }
- else {
- throw idade;
- }
- }
- catch (int idade) {
- cout << idade<<" é uma idade invalida!\n";
- }
- return 0;
- }
Nesse exemplo eu estou criando uma variável inteira chamada idade na linha 6, peço para o usuário digitar a idade dele nas linha 7 e 8 e passo a analisar a idade através de um conjunto if, else if, else . Note que da linha 9 a 14 eu estou apenas validando a idade para a possibilidade de dirigir.
No entanto, pode ser que usuário digite 0 ou digite uma palavra no lugar da idade. Nesse caso ele acaba caindo no bloco do else da linha 15 onde temos o throw que passa para o catch a idade como código de erro.
Nesse caso o catch precisa especificar na linha 19 o tipo de dado que é a idade, no caso, inteiro. Repare que na linha 20 eu justifiquei passar o valor da idade, pois a estou utilizando na saída da tela. Copie e cole esse código no GDB Online e teste digitando diversas idades, inclusive experimente digitar DEZOITO no lugar do número 18.
Com relação ao uso do setjmp() e longjmp() na linguagem C, apenas a título de curiosidade, deixarei abaixo um exemplo de uso dessas duas funções, mas alerto que não é algo para o usuário iniciante começar a mexer devido a complexidade de sua abstração.
- #include <stdio.h>
- #include <setjmp.h>
- int main() {
- jmp_buf salto;
- int bloco = setjmp(salto);
- if (bloco == 1) {
- printf("Estou no bloco %d\n",bloco);
- bloco = setjmp(salto);
- }
- if (bloco == 2) {
- printf("Estou no bloco %d\n",bloco);
- bloco = setjmp(salto);
- }
- if (bloco == 3) {
- printf("Estou no bloco %d\n",bloco);
- bloco = setjmp(salto);
- }
- if (bloco != 4){
- printf("passei por aqui\n");
- longjmp(salto, bloco + 1);
- }
- return 0;
- }
Para começar a descrever esse código devo esclarecer que as letras jmp vem de jump, que significa pular ou saltar. Assim setjmp vem de "definir o pulo". Para utilizar esses recursos precisamos incluir a biblioteca setjmp.h (linha 2).
A instrução jmp_buf salto; da linha 5 cria uma struct para armazenar o buffer desse jump. Buffer é uma área de memória para armazenar dados temporários. Chamamos essa struct de salto e criamos depois uma variável inteira chamada bloco cujo valor inicial será a definição desse salto, que inicia com zero.
Depois temos três blocos que só serão executados se o valor da variável bloco for 1, 2 ou 3 e finalmente um último bloco que imprime na tela "passei por aqui" e executa a longjmp(). Essa função restaura o buffer de salto e seu segundo parâmetro é o que ela retorna. No nosso caso ela está incrementando o valor do bloco.
Se você executar o código, por exemplo, no GDB Online terá como saída a figura abaixo e vai reparar que ele na primeira vez passa batido pelos três blocos de if, depois incrementando o bloco passará pelo primeiro if. Depois passará pelo segundo if, mas repare que precisará passar mais de uma vez para fazer isso. Complexo não?
![]() |
Tela do GDB Online mostrando o resultado de setjmp() e longjmp() |
Com isso encerramos esse minicurso básico de C++. Falta muita coisa para ser abordada, no entanto será mais produtivo iniciar o uso da framework Arduino e tratar do básico sobre o uso de componentes eletrônicos e microcontroladores.
Referências
DEITEL, H. M. DEITEL, P. J. C++: Como programar. Pearson Education do Brasil. 2006.
GBDONLINE. Learn C++ Programming. Disponível em: <https://learn.onlinegdb.com/c%2B%2B_for_beginners> Acesso em 05 ago. 2024.
W3SCHOOLS. C++ Tutorial. Disponível em: <https://www.w3schools.com/cpp/default.asp> Acesso em 05 ago. 2024.