Gestion des exceptions en langage C

Rédigé par niconux 12 commentaires
Classé dans : C/C++, Développement Mots clés : Exception, C

La bibliothèque thématique de programme en C se devait de traiter la gestion des exceptions qui est une manière très efficace de gérer les erreurs au sein d'un programme, quel qu'il soit.

Cet article s'efforcera de donner quelques implémentations de système de gestion d'exception au sein d'un programme écrit en langage C. Ces implémentations pourront souffrir de plus ou moins de limitations.

Dans des langages de programmations "modernes" (loin de moi de dire que le C est un langage du passé) comme le C++, Java ou C#, la gestion des exceptions se traduit par les instructions : try-throw-catch.

...
 try
{
 /* traitement, instruction, ... */
 }
 catch (TypeException e)
{
 /* gestion de l'exception : traitement de l'erreur */
}
 ... 

 

Voyons comment cette mécanique peut être implémentée en C.

Dans notre exemple précédent, toutes les instructions du bloc try peuvent déclencher (soulever) une exception qui sera traitée dans le bloc catch.
Si l'exception est de type TypeException alors le code présent dans le catch sera exécuté.

  • Fonctions setjmp et longjmp :

ANSI-C fournit de nombreuses fonctions : mathématiques (log, sqrt, ...), permettant la manipulation de chaînes de caractères (strcmp, ...) et des fonctions permettant de gérer les entrées/sorties (I/O) (getc, printf, ...).
Toutes ces fonctions sont très largement utilisées et non rien de compliqué, par contre deux fonctions s'avèrent très différentes et pas forcément simple à prendre en main.
Ces deux fonctions sont : setpjmp et longjmp, c'est ces deux fonctions qui vont nous permettre de gérer les différents sauts pour le traitement de l'exception.
 

  • Définitions des fonctions setjmp et longjmp :

setjmp et longjmp sont définit dans setjmp.h comme suit :
 

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

 

Les objets déclarés dans <setjmp.h> permettent d'éviter la séquence normale d'appel et de retour de fonction, ce qui s'utilise essentiellement pour revenir immédiatement d'une fonction profondément imbriquée.

La macro setjmp sauvegarde l'état du programme dans env, en vue de son utilisation par longjmp. setjmp retourne zéro en cas d'appel direct et une valeur non nulle en cas d'appel ultérieur via longjmp. On ne peut appeler longjmp que dans certains contextes, essentiellement à l'intérieur des tests de if, de switch et des boucles, et seulement dans des expressions simples.

longjmp remet le programme dans l'état sauvegardé lors du dernier appel à setjmp, grâce aux informations mémorisées dans env, et l'exécution reprend comme si la fonction setjmp venait de s'exécuter et avait retourné la valeur non nulle val. La fonction qui contient le setjmp ne doit pas être terminée. Les objets accessibles gardent les mêmes valeurs qu'au moment de l'appel de longjmp ; cependant, si des variables automatiques non volatiles de la fonction qui a appelé setjmp ont été modifiées depuis cet appel, leurs valeurs sont indéfinies après longjmp.

 
Pour de plus amples détails sur ces deux fonctions vous pouvez par exemple pour référer à la page wikipédia : setjmp.h (EN)
 

  • Implémentation Try-Catch :

 

#include <stdio.h>
#include <setjmp.h>

#define TRY do{ jmp_buf ex_buf; if( !setjmp(ex_buf) ){
#define CATCH } else {
#define ETRY } }while(0)
#define THROW longjmp(ex_buf, 1)

int main(int argc, char** argv)
{
   TRY
   {
      printf("Try...\n");
      THROW;
      printf("Dead code\n");
   }
   CATCH
   {
      printf("An exception rised!\n");
   }
   ETRY;

   return 0;
}


L'idée de cette implémentation repose sur le mapping du TRY sur une instruction if.
Au premier appel cela retourne 0 et le code exécuté est celui se trouvant le bloc du then. CATCH est simplement le bloc else. Quand le bloc THROW est exécuté, cela appelle la fonction longjmp avec comme valeur pour le second paramètre 1 (en fait autre chose que 0).
Cette implémentation propose aussi un bloc ETRY qui représente la fin du bloc try-throw-catch. C'est  voulu car toutes les opérations faites dans le try-throw-catch interviennent dans le cadre d'une boucle do-while.

Deux raisons importantes à cela :

  1. L'instruction TRY-ETRY est gérée comme un seul bloc
  2. Définir de multiples instructions TRY-ETRY dans le même bloc (réutilisation de la variable ex_buf)
  • Implémentation Try-Catch - multi-exceptions :

Une gestion d'exception dans un cas réel a la possibilité de gérer de multiples exceptions et de différentes natures.

Pour répondre à ce fonctionnel, il est nécessaire d'opérer à certaines modifications à l'exemple précédent.

L'instruction TRY-ETRY est traduit par un switch au lieu d'un if. Chaque instruction CATCH n'est plus un simple else, mais un case.
CATCH devient maintenant une macro avec paramètre. Le paramètre représente la nature de l'exception traité dans le bloc.
Chaque instruction CATCH doit fermer le case précédent (avec un break).
 

#include <stdio.h>
#include <setjmp.h>

#define TRY do{ jmp_buf ex_buf; switch( setjmp(ex_buf) ){ case 0:
#define CATCH(x) break; case x:
#define ETRY } }while(0)
#define THROW(x) longjmp(ex_buf, x)

#define MISMATCH_EXCEPTION (1)
#define NULL_EXCEPTION (2)
#define TYPE_EXCEPTION (3)

int main(int argc, char** argv)
{
   TRY
   {
      printf("Try...\n");
      THROW( NULL_EXCEPTION );
      printf("Dead code\n");
   }
   CATCH( MISMATCH_EXCEPTION )
   {
      printf("Mismatch exception rised !\n");
   }
   CATCH( NULL_EXCEPTION )
   {
      printf("Null exception rised !\n");
   }
   CATCH( TYPE_EXCEPTION )
   {
      printf("Type exception rised!\n");
   }
   ETRY;

   return 0;
}

 

  • Implémentation Try-Catch-Finally :

Dans cette dernière implémentation, nous allons mettre en place la gestion du finally. Le bloc finally permet d'être exécuté après le bloc try ou n'importe quel bloc catch.

L'exécution du finally est possible dans les trois cas suivants :

  1. Après un bloc TRY
  2. Après un bloc CATCH
  3. Quand un type d'exception n'est pas connu.
#include <stdio.h>
#include <setjmp.h>

#define TRY do{ jmp_buf ex_buf; switch( setjmp(ex_buf) ){ case 0: while(1){
#define CATCH(x) break; case x:
#define FINALLY break; } default:
#define ETRY } }while(0)
#define THROW(x) longjmp(ex_buf, x)

#define MISMATCH_EXCEPTION (1)
#define NULL_EXCEPTION (2)
#define TYPE_EXCEPTION (3)

int main(int argc, char** argv)
{
   TRY
   {
      printf("Try...\n");
      THROW( NULL_EXCEPTION );
      printf("Dead code\n");
   }
   CATCH( MISMATCH_EXCEPTION )
   {
      printf("Mismatch exception rised !\n");
   }
   CATCH( NULL_EXCEPTION )
   {
      printf("Null exception rised !\n");
   }
   CATCH( TYPE_EXCEPTION )
   {
      printf("Type exception rised!\n");
   }
   FINALLY
   {
      printf("... finally\n");
   }
   ETRY;

   return 0;
}

 

Malgré les limitations que l'on a pu voir, il est possible de mettre en place un système de gestion d'exceptions dans un programme C, même si l'on ne peut pas profiter de toutes les fonctionnalités que l'on peut retrouver dans le système d'exception en Java, C++, ...

Vous pouvez retrouver d'autres articles et programmes dans la bibliothèque thématique réservée au langage C.

12 commentaires

#1  - https://talkaboutnet.com/ a dit :

Hmm it looks like your website ate my first comment (it was extremely long) so I guess I'll just sum it up what I had written and
say, I'm thoroughly enjoying your blog. I as well
am an aspiring blog writer but I'm still new to everything.
Do you have any helpful hints for beginner blog writers?
I'd genuinely appreciate it.

Répondre
#2  - sex trẻ em a dit :

Pretty nice post. I just stumbled upon your blog and wished to say that I have really enjoyed browsing your blog posts.
After all I'll be subscribing to your feed and I hope you write again soon!

Répondre
#3  - 18win bond a dit :

Hi there, You've done an incredible job. I will definitely digg it and personally
suggest to my friends. I'm sure they will
be benefited from this website.

Répondre
#4  - PHIM XEX LOẠN LUẬN GOOGLE VIỆT NAM a dit :

I needed to thank you for this great read!! I definitely loved every little bit of it.
I've got you saved as a favorite to check out new things you
post…

Répondre
#5  - https://win88best.com/ a dit :

Thanks for every other wonderful article. The place else may just anyone get
that kind of info in such an ideal way of writing?
I have a presentation next week, and I'm at the look for such
information.

Répondre
#6  - sv66 casino a dit :

Thank you a bunch for sharing this with all people you really understand what
you're speaking about! Bookmarked. Please also visit my website
=). We may have a link trade arrangement among us

Répondre
#7  - sex việt nam gái xinh múp nõn a dit :

obviously like your web site however you
need to test the spelling on several of your posts.
Many of them are rife with spelling problems and
I find it very bothersome to tell the truth nevertheless I will surely
come back again.

Répondre
#8  - sex việt nam gái xinh múp nõn a dit :

I'm amazed, I have to admit. Rarely do I come across a blog that's both equally educative
and interesting, and without a doubt, you have hit the nail on the head.
The issue is something that not enough people are speaking intelligently about.

Now i'm very happy I came across this in my hunt for something relating to this.

Répondre
#9  - sex trẻ em a dit :

Hi there! This post couldn't be written any better! Reading through this
post reminds me of my old room mate! He always kept chatting about this.
I will forward this write-up to him. Pretty sure he
will have a good read. Thank you for sharing!

Répondre
#10  - sex việt nam gái xinh múp nõn a dit :

I was suggested this web site by my cousin. I'm not sure whether this post
is written by him as nobody else know such detailed about my difficulty.
You are wonderful! Thanks!

Répondre
#11  - phim sex không che a dit :

I am regular reader, how are you everybody? This article posted at this website
is really good.

Répondre
#12  - sex trẻ em full HD xem sex uy tín 888b a dit :

Spot on with this write-up, I really believe this website needs far more attention. I'll probably be back again to read through more, thanks for the
info!

Répondre

Écrire un commentaire

Quelle est le deuxième caractère du mot 0wrmnf ?

Fil RSS des commentaires de cet article