Tratamento de exceções na linguagem C

Uma implementação de tratamento de exceções usando a linguagem C, discutindo vários modelos e suas limitações, possíveis vazamentos de memórias, testes comparativos, muitos exemplos, introdução a certos recursos da linguagem, ... É certamente um assunto interessante se você quer expandir seus conhecimentos da linguagem C.

[ Hits: 69.373 ]

Por: Vinícius dos Santos Oliveira em 11/11/2010 | Blog: https://vinipsmaker.github.io/


Macros



Após toda essa discussão sabemos exatamente como alcançar, em C, o comportamento que ocorre com tratamento de exceções em linguagens de alto nível como C++. Porém a viabilidade do uso das técnicas desenvolvidas nesse texto está ameaçada devido a grande quantidade de código repetitivo que se faz necessário. Para contornar esse problema, pode-se utilizar outra grande funcionalidade presente na linguagem, o preprocessador de macros.

Há um padrão simples que ocorre nesses códigos repetitivos e podemos implementar macros que automatizem essa parte do trabalho facilmente. Primeiro, percebemos que um bloco try é composto pela declaração das variáveis jmp_buf e struct _gvalue e pelo bloco if contendo a negação do valor de retorno de uma chamada a função setjmp recebendo como argumento a variável declarada como sendo do tipo jmp_buf:

#define TRY \
  { \
    jmp_buf _eb; \
    struct _gvalue _ev = {NULL, NULL}; \
    struct _gvalue * const _evp = &_ev \
    if (!setjmp(_eb)) {
#define CATCH(_type, _value) \
    } else if (_ev.name && !strcmp(_ev.name, #_type)) { \
      _type _value = *((_type *)(_ev.value));
#define ENDTRY \
    } \
    if (_ev.value) free(_ev.value); \
  }

Para esse conjunto de macros, uma macro THROW adequada seria:

#define THROW(_type, _value) \
  { \
    if (_evp) { \
      _evp->name = #_type; \
      _evp->value = malloc(sizeof(_type)); \
      *((_type *)(_evp->value)) = _value; \
    } \
    longjmp(_eb, 1); \
  }

Com essas macros, caso seja feito um pulo para fora de um bloco CATCH, haverá um vazamento de memória. Também, a ordem TRY-CATCH-ENDTRY deve ser preservada, com os blocos CATCH opcionais (apesar de que essa prática não é recomendada).

Para declarar e usar funções que disparam exceções, as macros abaixo seriam necessárias:

#define THROW_ARGS jmp_buf _eb, struct _gvalue *_evp
#define TRY_ARGS _eb, _evp

Com essas macros, pode-se tratar exceções em C da forma a seguir:

#include "cexceptions.h"
#include <stdio.h>

int divide(int a, int b, THROW_ARGS); // throw const char *

int main()
{
  TRY
    printf("%i\n", divide(1, 0, TRY_ARGS));
  CATCH(const char *, stre)
    printf("Erro: %s\n", stre);
  ENDTRY
  return 0;
}

int divide(int a, int b, THROW_ARGS)
{
  if (b)
    return a / b;
  else
    THROW(const char *, "Divisão por 0 impossível no conjunto dos números inteiros");
}

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Tratamento de exceções em C
   3. Quebra de fluxo de execução, goto e setjmp
   4. Exceções associadas a inteiros
   5. Informação sobre os tipos em tempo de execução
   6. Macros
   7. Aninhando exceções
   8. Mais macros
   9. Memory leaks
   10. Uso em dispositivos móveis
   11. Conclusão
Outros artigos deste autor

A história do hardware

GNU Emacs, o primeiro GNU

A história do ogg na web

História da informática: Um pouco de datas e especificações

Entendendo os codecs, os containers formats e por que o Ogg é tão bom

Leitura recomendada

Android NDK: Desmistificando o acesso a códigos nativos em C

Desenvolvendo aplicativo para autenticação biométrica utilizando a Libfprint

Instalando Facebook Folly através do Conan

Programação de Jogos com SDL

Acessando a porta paralela via Linux

  
Comentários
[1] Comentário enviado por removido em 11/11/2010 - 17:16h

Gostei da aparência do código usando macros para definir os blocos try, catch e throw.

E parabéns pela contribuição de suas idéias!

[2] Comentário enviado por mslomp em 11/11/2010 - 18:17h

permita-me contribuir com conteúdo referente a esse assunto, a quem interessar:
há um tempo atrás postei na seção Scripts um código referente a isso:
http://www.vivaolinux.com.br/script/Excecoes-em-C-atraves-de-trythrowcatch

baseado na questão de um usuário em:
http://www.vivaolinux.com.br/topico/C-C++/C-e-Java

parabéns, um ótimo artigo conceitual e referencial

[3] Comentário enviado por SamL em 12/11/2010 - 12:06h

Cara gostei do artigo, nota 10.
Usar essas macros deixa um código bem mais limpo e organizado.

[4] Comentário enviado por gedarius em 12/11/2010 - 12:06h

ótimo artigo, parabéns!!!!

[5] Comentário enviado por vinipsmaker em 12/11/2010 - 15:47h

@mslomp, vlw, é bom saber que esse assunto interessa a muitos.

E aos outros, agradeço os elogios (críticas também são bem-vindas, caso tenham alguma =D ).

[6] Comentário enviado por mazinsw em 12/11/2010 - 19:41h

valeu pela contribuição, eu não sabia usar macros agora está mais fácil.

[7] Comentário enviado por vinipsmaker em 02/03/2013 - 19:19h

Migrei o código para https://github.com/vinipsmaker/c-except


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts