Une erreur de gestion d'erreur

Sur un exemple du tutoriel C

Le problème exposé dans ce sujet a été résolu.

Hello !

Je me suis mis récemment en tête de compléter le tutoriel sur le C. J’en suis actuellement à la gestion d’erreur (partie 1) et je suis tombé sur un comportement que je n’arrive pas à comprendre et pour lequel mes recherches n’ont pas fourni d’explications.

Le code est celui fourni par le tutoriel pour expliquer l’utilisation de errno auquel j’ai ajouté #include <math.h>

De ce que je comprends, il est censé ne rien afficher, mais il m’affiche un résultat quoi que je fasse.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <errno.h>
#include <math.h>
#include <stdio.h>


int main(void)
{
    double x;

    errno = 0;
    x = pow(-1, 0.5);

    if (errno == 0)
        printf("x = %f\n", x);

    return 0;
}
1
x = nan

La commande que j’utilise pour la compilation est zcc -lm test_errno.c; ./a.out, zcc étant l’alias de la commande de compilation fournie au début du cours, elle correspond à gcc -Wall -Wextra -pedantic -std=c89 -fno-common -fno-builtin.

J’ai tenté de produire des erreurs avec d’autres fonctions mathématiques ($log(-1)$ par exemple) mais rien n’a abouti. J’ai testé sur un compilateur en ligne et cette fois ci, le code a fonctionné comme prévu.

Avez-vous la moindre idée de pourquoi j’ai ce problème et comment puis-je le résoudre ?

Merci d’avance ! :)

+0 -0

Salut,

Je me suis mis récemment en tête de compléter le tutoriel sur le C.

Poliorcetics

Et je t’en remercie vivement. ;)

J’en suis actuellement à la gestion d’erreur (partie 1) et je suis tombé sur un comportement que je n’arrive pas à comprendre et pour lequel mes recherches n’ont pas fourni d’explications […]

Poliorcetics

Techniquement, ton code est parfaitement correct et n’importe quelle implémentation de la bibliothèque standard conforme à la norme (c89/c90) devrait modifier la valeur de la variable errno vers EDOM. C’est par exemple le cas de la Glibc (l’implémentation développée par le projet GNU) qui est employée sous GNU/Linux et avec laquelle j’ai effectuée mes tests.

Toutefois, à ma grande surprise, ce n’est pas le cas d’autres implémentations à commencer par celle du projet OpenBSD qui semble uniquement modifier la valeur de la variable errno dans le cas où les flottants ne sont pas représenté suivant la norme IEE 754.

Note que, depuis la norme C99, la modification de la variable errno semble ne plus être obligatoire (mais cela ne justifie pas le comportement en cas d’emploie de la norme C89). Il est possible de le savoir à l’aide de la macroconstante math_errhandling (définie dans l’en-tête <math.h>). Une valeur de 1 ou 3 indique que la variable errno est modifiée, une valeur de 2 indique que ce n’est pas le cas (c’est la valeur que j’obtiens sous OpenBSD).

Je tâcherai d’ajouter une note à ce sujet une fois la version publique du tuto revenue. :)

+2 -0

Merci beaucoup pour l’explication!

Effectivement, la valeur de math_errhandling que j’ai est 2. Je ne sais pas ci cela peut aider mais j’utilise un Mac avec les dernières versions de l’OS, de Xcode et des Developer Tools.

Je n’arrive pas à ’attraper’ l’erreur du coup, une idée ? À part tester les arguments fournis à la fonction en avance, je ne vois pas comment faire.

+0 -0

Effectivement, la valeur de math_errhandling que j’ai est 2. Je ne sais pas ci cela peut aider mais j’utilise un Mac avec les dernières versions de l’OS, de Xcode et des Developer Tools.

Poliorcetics

Mmm… Vu que Mac OS X se base (basait ?) sur FreeBSD, ce n’est pas impossible que le même système que sous OpenBSD soit employé.

Je n’arrive pas à ’attraper’ l’erreur du coup, une idée ? À part tester les arguments fournis à la fonction en avance, je ne vois pas comment faire.

Poliorcetics

En fait, si la norme IEEE 754 est d’application (ce qui, pour ainsi dire, est toujours le cas), tu peux détecter une erreur étant donné que les flottants disposes de valeurs particulières, notamment NaN (pour « Not a Number »). Tu peux vérifier cela à l’aide de la macrofonction isnan() (introduite en C99) définie dans l’en-tête <math.h>. Du coup, tu peux modifier ton code comme suit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <errno.h>
#include <math.h>
#include <stdio.h>


int main(void)
{
    double x;

    errno = 0;
    x = pow(-1, 0.5);

    if (errno == 0 && !isnan(x))
        printf("x = %f\n", x);

    return 0;
}
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte