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

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


Uso em dispositivos móveis



Em alguns dispositivos embarcados, é encorajado o uso da linguagem C para obter-se um melhor aproveitamento de recursos, que nesses dispositivos é escasso. Nessa seção coloco informações sobre comparativos sobre o tempo de execução feitos com programas que usam tratamento de exceções, usando a implementação descrita nesse texto, e seus equivalentes em C++.

A máquina utilizada para testes um PC com um processador Intel(R) Core(TM)2 Duo CPU E7400 @ 2.80GHz e 3gb de memória ram rodando a distribuição Ubuntu 10.4 32-bit kernel 2.6.32-25-generic e o compilador utilizado foi o GCC 4.4.3.

Num primeiro teste, fazemos programa simples, que apenas chama uma função que não faz nada. Para evitar otimizações pelo compilador, coloquei cada função em um arquivo separado.

CExcept:

void a(THROW_NAMED_ARGS())
{
  return;
}

int main()
{
  {
    int32_t i = 0;
    for (;i < 2147483647;++i) {
      TRY()
        a(TRY_ARGS());
      CATCHANY
        ;
      ENDTRY()
    }
  }
}

C++:

void a()
{
  return;
}

int main()
{
  {
    int32_t i = 0;
    for (;i < 2147483647;++i) {
      try {
        a();
      } catch(...) {
        ;
      }
    }
  }
}

Usando o programa time (http://www.gnu.org/software/time/), coletei informações sobre a execução desses programas, e as respectivas saídas foram:

CExcept:

User time (seconds): 18.42
System time (seconds): 0.00
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:18.48
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 1200
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 119
Voluntary context switches: 1
Involuntary context switches: 2888
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0


C++:

User time (seconds): 6.12
System time (seconds): 0.01
Percent of CPU this job got: 98%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:06.22
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 2704
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 227
Voluntary context switches: 1
Involuntary context switches: 1412
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0


Nesse primeiro teste, o processo que contém o tratamento de exceções implementado nativamente pelo compilador C++ terminou sua execução 3 vezes mais rápido, aproximadamente. Executei o teste várias vezes e os resultados foram similares. Agora modificando a implementação da função a, para que dispare uma exceção:

CExcept:

void a(THROW_NAMED_ARGS())
{
  THROW(int, 0,)
}

C++:

void a()
{
  throw(0);
}

E os resultados dos novos testes:

CExcept:

User time (seconds): 132.98
System time (seconds): 0.09
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 2:13.61
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 1392
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 131
Voluntary context switches: 1
Involuntary context switches: 32078
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0


C++:

User time (seconds): 7914.17
System time (seconds): 3.92
Percent of CPU this job got: 98%
Elapsed (wall clock) time (h:mm:ss or m:ss): 2:13:48
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 3200
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 258
Voluntary context switches: 1
Involuntary context switches: 2177657
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0


Agora a versão implementada em C mostra-se mais rápida (59 vezes mais rápida). Também executei esse teste várias vezes e os resultados foram similares.

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

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

GNU Emacs, o primeiro GNU

A história do hardware

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

Aplicativos web em C++ usando o Tufão

Leitura recomendada

Como funcionam os alocadores de memória do STD C?

Desenvolvendo para microcontroladores em GNU/Linux

Compilando o Mono 2.2 no Ubuntu 8.10

OneAPI: A plataforma da Intel para facilitar o desenvolvimento com chips Intel, AMD, ARM, NVIDIA POWER e FPGA

Algum humor e C++ Design Patterns (parte 1)

  
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