Gestion des erreurs avec setjump/longjump
Bonjour,
je viens de découvrir un façon assez original de gérer les erreurs dans un code. Plutot que d'utiliser la valeur de retour des fonctions, l'idée est d'appeler setjump avant l'appel à une fonction critique puis longjump en cas d'erreur. Voici le code proposé en exemple :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| #include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <setjmp.h>
#define CARACTERE_INCORRECT 1
#define ECHAPPEMENT_INCORRECT 2
#define DEFAUT_DE_MEMOIRE 3
static jmp_buf contexte;
static char caractere_incorrect;
static char *
fin_de_la_chaine(int longueur)
{
if (longueur == 0)
return NULL;
char *s = malloc(longueur + 1);
if (s == NULL)
longjmp(contexte, DEFAUT_DE_MEMOIRE);
s = s + longueur;
*s = '\0';
return s;
}
static int
continuation_ligne_suivante(int c1)
{
if (c1 != '\\')
return 0;
int c2 = getchar();
if (c2 == '\n')
return 1;
caractere_incorrect = c2;
longjmp(contexte, ECHAPPEMENT_INCORRECT);
}
static char *
defiler_entier(int longueur)
{
int c = getchar();
if (c == EOF || isspace(c) || c == '.')
return fin_de_la_chaine(longueur);
if (continuation_ligne_suivante(c))
return defiler_entier(longueur);
else if (isdigit(c))
{
char *s = defiler_entier(longueur + 1);
*--s = c;
return s;
}
else
{
caractere_incorrect = c;
longjmp(contexte, CARACTERE_INCORRECT);
}
}
int
main(void)
{
char *s;
switch(setjmp(contexte))
{
case 0 :
s = defiler_entier(0);
break;
case CARACTERE_INCORRECT :
fprintf(stderr, "'%c': caractère incorrect\n",
caractere_incorrect);
return EXIT_FAILURE;
case ECHAPPEMENT_INCORRECT :
fprintf(stderr, "'\\%c': échappement incorrect\n",
caractere_incorrect);
return EXIT_FAILURE;
case DEFAUT_DE_MEMOIRE :
fprintf(stderr, "Défaut de mémoire\n");
return EXIT_FAILURE;
}
printf("%s\n", s);
return EXIT_SUCCESS;
} |
Vous en pensez quoi ?
Mis à part l'utilisation d'une variable globale pour sauvegarder le contexte et le manque d'information concernant l'erreur (ce code utilise une variable globale pour transmettre le caractère qui a causé l'erreur mais dans un code plus important cela me semble difficilement possible), cette méthode me parrait plus interessante qu'une succession d'accolade.
Re: Gestion des erreurs avec setjump/longjump
Citation:
Envoyé par gege2061
je viens de découvrir un façon assez original de gérer les erreurs dans un code. Plutot que d'utiliser la valeur de retour des fonctions, l'idée est d'appeler setjump avant l'appel à une fonction critique puis longjump en cas d'erreur.
Oui, c'est une façon bien connue d'implémenter try-catch... Ca revient à faire un super goto (hors d'un bloc). Il vaut savoir ce qu'on fait...