« Programmation C/Erreurs » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
Aucun résumé des modifications
Alveric (discussion | contributions)
Mise en page, ajout d'un exemple, et corrections
Ligne 1 : Ligne 1 :
{{Programmation C}}
{{Programmation C}}


Le langage C fournit un en-tête spécialisé pour la gestion des erreurs : '''errno.h'''. Cet en-tête déclare notamment une variable globale '''errno''', et un certain nombre de codes d'erreur, qui permettent aux fonctions de la bibliothèque standard de reporter précisément la cause d'une erreur.
Une bibliothéque spécialisée existe pour la gestion des erreurs : ''errno.h''.


== Utilisation ==
Pour l'inclure dans son fichier source, ou projet, il faut ajouter la ligne :
Pour inclure l'en-tête dans son fichier source, ou projet, il faut ajouter la ligne :
#include <errno.h>
#include <errno.h>
On peut alors utiliser la variable '''errno''', de type '''int''', pour traiter les erreurs<ref name="typeErrno">'''errno''' peut être définie par une macro ou un identificateur.</ref>.


Lorsqu'on veut utiliser '''errno''' pour déterminer si un appel de fonction a bien fonctionné, ou pour préciser quelle est l'erreur si elle a échoué, il est nécessaire de mettre la variable à 0 avant de procéder à l'appel de la fonction. Ensuite, après l'appel de la fonction, on peut déterminer l'erreur (s'il y en a une) en comparant la valeur avec un certain nombre de macro définies dans '''errno.h'''.
et également ajouter une variable globale :
extern int errno;


== Exemple ==
Il est conseillé de mettre à 0 la valeur d'''errno'' avant d'effectuer un appel à une fonction qui pourrait modifier dynamiquement la valeur de la variable entière (0 signifiant qu'aucune erreur n'a été rencontrée).
Pour illustrer cela, voici un exemple, qui tente de convertir une chaine de caractères en un nombre. Le nombre donné, 2<sup>64</sup>, peut ne pas être dans le domaine de valeur du type '''unsigned long''' (qui peut se limiter à 2<sup>32</sup> - 1), suivant l'implémentation qui est utilisée pour l'exécuter. Dans ce cas, on utilise '''errno''' pour afficher un message d'erreur approprié à l'utilisateur.


<pre>
Les codes d'erreurs suivants peuvent être présents dans errno :
#include <stdio.h> /* puts(), printf(), NULL */
#include <stdlib.h> /* strtoul() */
#include <limits.h> /* ULONG_MAX */
#include <errno.h> /* errno et ERANGE */

void teste(const char *nombre)
{
errno = 0;
unsigned long res = strtoul(nombre, NULL, 10);
if (res == ULONG_MAX)
{
/* il y a eu une erreur ! */
if (errno == ERANGE)
{
/* on sait quelle est l'erreur */
puts("L'erreur rencontree est une erreur de domaine.");
}
else
{
/* pas d'information précise à fournir à l'utilisateur */
puts("Une erreur a ete rencontree.");
}
}
else
{
printf("La conversion a ete effectuee, et la valeur est: %ld\n", res);
}
}

int main(void)
{
/* 2 puissance 8 : sera toujours accepte */
teste("256");

/* 2 puissance 64 : peut echouer suivant la machine */
teste("18446744073709551616");
return 0;
}</pre>
Si '''unsigned long''' est codé sur 32 bits (c'est le cas sur la plupart des architectures de types PC en 32 bits), on peut obtenir:
ULONG_MAX vaut 4294967295l.
La conversion a ete effectuee, et la valeur est: 256
L'erreur rencontree est une erreur de domaine.

Il est nécessaire de placer '''errno''' à 0 ''avant'' d'utiliser '''strtoul''', car les fonctions de la bibliothèque standard ne sont pas obligées de la mettre à zéro en cas de succès. À cause de celà, si on ne la réinitialisait pas «&nbsp;manuellement&nbsp;», on pourrait voir le résultat d'une erreur précédente, causée par une autre fonction. C'est une des lourdeurs du modèle de gestion d'erreur du C...

'''Note&nbsp;:''' Le contrôle d'erreur des fonctions '''strto*''' est en réalité plus complexe, puisque le deuxième paramètre permet un contrôle plus fin. Il n'est pas utilisé ici, pour se concentrer sur '''errno''', mais devrait l'être dans un vrai programme.

== Erreurs possibles ==
Les codes d'erreurs suivants sont définis&nbsp;:
* EDOM
* EILSEQ
* ERANGE

Une implémentation peut fournir, en plus des 3 précédents, autant de valeurs pour '''errno''' qu'elle le souhaite. Ci-dessous se trouve une liste d'erreurs présentes sur différents systèmes:
* E2BIG
* E2BIG
* EACCES
* EACCES
Ligne 29 : Ligne 85 :
* EDEADLK
* EDEADLK
* EDESTADDRREQ
* EDESTADDRREQ
* EDOM
* EDQUOT
* EDQUOT
* EEXIST
* EEXIST
Ligne 36 : Ligne 91 :
* EHOSTUNREACH
* EHOSTUNREACH
* EIDRM
* EIDRM
* EILSEQ
* EINPROGRESS
* EINPROGRESS
* EINTR
* EINTR
Ligne 81 : Ligne 135 :
* EPROTONOSUPPORT
* EPROTONOSUPPORT
* EPROTOTYPE
* EPROTOTYPE
* ERANGE
* EROFS
* EROFS
* ESPIPE
* ESPIPE
Ligne 91 : Ligne 144 :
* EWOULDBLOCK
* EWOULDBLOCK
* EXDEV
* EXDEV

== Notes ==

<references />

Version du 14 juin 2006 à 14:15


Le langage C fournit un en-tête spécialisé pour la gestion des erreurs : errno.h. Cet en-tête déclare notamment une variable globale errno, et un certain nombre de codes d'erreur, qui permettent aux fonctions de la bibliothèque standard de reporter précisément la cause d'une erreur.

Utilisation

Pour inclure l'en-tête dans son fichier source, ou projet, il faut ajouter la ligne :

#include <errno.h>

On peut alors utiliser la variable errno, de type int, pour traiter les erreurs[1].

Lorsqu'on veut utiliser errno pour déterminer si un appel de fonction a bien fonctionné, ou pour préciser quelle est l'erreur si elle a échoué, il est nécessaire de mettre la variable à 0 avant de procéder à l'appel de la fonction. Ensuite, après l'appel de la fonction, on peut déterminer l'erreur (s'il y en a une) en comparant la valeur avec un certain nombre de macro définies dans errno.h.

Exemple

Pour illustrer cela, voici un exemple, qui tente de convertir une chaine de caractères en un nombre. Le nombre donné, 264, peut ne pas être dans le domaine de valeur du type unsigned long (qui peut se limiter à 232 - 1), suivant l'implémentation qui est utilisée pour l'exécuter. Dans ce cas, on utilise errno pour afficher un message d'erreur approprié à l'utilisateur.

#include <stdio.h>  /* puts(), printf(), NULL */
#include <stdlib.h> /* strtoul() */
#include <limits.h> /* ULONG_MAX */
#include <errno.h>  /* errno et ERANGE */

void teste(const char *nombre)
{
    errno = 0;
    unsigned long res = strtoul(nombre, NULL, 10);
    if (res == ULONG_MAX)
    {
        /* il y a eu une erreur ! */
        if (errno == ERANGE)
        {
            /* on sait quelle est l'erreur */
            puts("L'erreur rencontree est une erreur de domaine.");
        }
        else
        {
            /* pas d'information précise à fournir à l'utilisateur */
            puts("Une erreur a ete rencontree.");
        }
    }
    else
    {
        printf("La conversion a ete effectuee, et la valeur est: %ld\n", res);
    }
}

int main(void)
{
    /* 2 puissance 8 : sera toujours accepte */
    teste("256");

    /* 2 puissance 64 : peut echouer suivant la machine */
    teste("18446744073709551616");
    return 0;
}

Si unsigned long est codé sur 32 bits (c'est le cas sur la plupart des architectures de types PC en 32 bits), on peut obtenir:

ULONG_MAX vaut 4294967295l.
La conversion a ete effectuee, et la valeur est: 256
L'erreur rencontree est une erreur de domaine.

Il est nécessaire de placer errno à 0 avant d'utiliser strtoul, car les fonctions de la bibliothèque standard ne sont pas obligées de la mettre à zéro en cas de succès. À cause de celà, si on ne la réinitialisait pas « manuellement », on pourrait voir le résultat d'une erreur précédente, causée par une autre fonction. C'est une des lourdeurs du modèle de gestion d'erreur du C...

Note : Le contrôle d'erreur des fonctions strto* est en réalité plus complexe, puisque le deuxième paramètre permet un contrôle plus fin. Il n'est pas utilisé ici, pour se concentrer sur errno, mais devrait l'être dans un vrai programme.

Erreurs possibles

Les codes d'erreurs suivants sont définis :

  • EDOM
  • EILSEQ
  • ERANGE

Une implémentation peut fournir, en plus des 3 précédents, autant de valeurs pour errno qu'elle le souhaite. Ci-dessous se trouve une liste d'erreurs présentes sur différents systèmes:

  • E2BIG
  • EACCES
  • EADDRINUSE
  • EADDRNOTAVAIL
  • EAFNOSUPPORT
  • EAGAIN
  • EALREADY
  • EBADF
  • EBADMSG
  • EBUSY
  • ECANCELED
  • ECHILD
  • ECONNABORTED
  • ECONNREFUSED
  • ECONNRESET
  • EDEADLK
  • EDESTADDRREQ
  • EDQUOT
  • EEXIST
  • EFAULT
  • EFBIG
  • EHOSTUNREACH
  • EIDRM
  • EINPROGRESS
  • EINTR
  • EINVAL
  • EIO
  • EISCONN
  • EISDIR
  • ELOOP
  • EMFILE
  • EMLINK
  • EMSGSIZE
  • EMULTIHOP
  • ENAMETOOLONG
  • ENETDOWN
  • ENETRESET
  • ENETUNREACH
  • ENFILE
  • ENOBUFS
  • ENODATA
  • ENODEV
  • ENOENT
  • ENOEXEC
  • ENOLCK
  • ENOLINK
  • ENOMEM
  • ENOMSG
  • ENOTPROTOOPT
  • ENOSPC
  • ENOSR
  • ENOSTR
  • ENOSYS
  • ENOTCON
  • ENOTDIR
  • ENOTEMPTY
  • ENOTSOCK
  • ENOTSUP
  • ENOTTY
  • ENXIO
  • EOPNOTSUPP
  • EOVERFLOW
  • EPERM
  • EPIPE
  • EPROTO
  • EPROTONOSUPPORT
  • EPROTOTYPE
  • EROFS
  • ESPIPE
  • ESRCH
  • ESTALE
  • ETIME
  • ETIMEDOUT
  • ETXTBSY
  • EWOULDBLOCK
  • EXDEV

Notes

  1. errno peut être définie par une macro ou un identificateur.