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.261 ]

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


Introdução



Em linguagens de programação de alto nível tais como C++, Python e Java, há o recurso de tratamento de exceções, que permite que programadores escrevam blocos try - catch e funções/métodos que disparem exceções.

Com uso de tais recursos, o fluxo de lógica do programa fica no bloco try, separado do tratamento das exceções, que ficam no bloco catch. O uso primário do tratamento de exceções é separar o fluxo da lógica do fluxo de tratamento de erros (nesse caso usa-se exceções para identificar os erros). Dentro dessa abordagem, as exceções são usadas para indicar erros que ocorrem. Tratamento de exceções, atualmente, é uma técnica desejável em muitos ambiente de desenvolvimento.

Programadores de C, geralmente utilizam o valor de retorno da função para indicar algum erro, como ocorre nas funções de alocação dinâmica, por exemplo. Essa abordagem é adequada a proposta da linguagem de ser uma linguagem de médio nível eficiente, porém nem sempre é adequada ao desenvolvimento do software. Em uma função onde todo valor de retorno é válido, essa abordagem mostra-se ineficaz, e a elegância do código seria ameaçada para resolver tal problema, como mostra o exemplo.

int divide1(int a, int b, int *ok)
{
  if (b) {
    if (ok)
      *ok = 1;
    return a / b;
  } else {
    if (ok)
      ok = 0;
    return 0;
  }
}

struct ret
{
  int ok;
  int value;
};

struct ret divide2(int a, int b)
{
  struct ret res = {1, 0};

  if (b)
    res.value = a / b;
  else
    res.ok = 0;

  return res;
}

int main()
{
  int i;
  {
    int ok;
    // A and B should be defined as macros
    int unsafe_value = divide1(A, B, &ok);
    if (ok)
      i = unsafe_value;
  }
  {
    struct ret tmp = divide2(A, B);
    if (tmp.ok)
      i = tmp.value;
  }
  return 0;
}

Uma prática que vem substituindo com sucesso o uso de valores de retorno para a indicação de erros é o uso de exceções. Essa prática traz vários benefícios, principalmente relacionados com a legibilidade e manutenção do código.

Neste texto, serão demonstradas as funcionalidades requeridas para que o tratamento de exceções seja aplicado e será feita a apresentação de uma implementação na linguagem de programação C, que é uma das linguagens de médio nível mais populares. Por ser uma linguagem de médio nível, adotar tratamento de exceções como parte do padrão que define a linguagem pode não ser adequado, pois o código-fonte iria esconder certos comportamentos, que não é característico em uma linguagem de médio nível.

Assim sendo, este artigo tem por objetivo:

i) apresentar técnicas que imitem o tratamento de exceções que expõem a implementação proposta;
ii) descrever facilidades implementadas através de macros que viabilizam seu uso e;
iii) avaliar o desempenho.

Nesse texto foi adotada uma abordagem incremental, onde há uma definição simples do tratamento de exceções no início, e a cada seção teremos uma definição mais próxima da utilizada na programação no mundo real.

    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

Mupen64plus, o melhor emulador de Nintendo 64 disponível para GNU/Linux

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

Aplicativos web em C++ usando o Tufão

Próximas Tecnologias do Sistema GNU/Linux

Leitura recomendada

Programação com números inteiros gigantes

Tutorial OpenGL v3.0

Desenvolvendo para microcontroladores em GNU/Linux

Parâmetros interessantes do scanf e do printf em C

A duplicação do buffer de saída na chamada de sistema fork() do 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