La gestion des erreurs en langage C a toujours été la tâche du développeur. La bibliothèque standard ne dispose pas d'exceptions, les erreurs sont retournées par des codes de retour ou une variable globale errno (utilisation initiale — UNIX des années 1970, puis POSIX et ANSI C). De tels mécanismes sont encore utilisés aujourd'hui pour gérer le flux d'exécution en cas de situations imprévues.
Les erreurs lors de l'utilisation des fonctions standard (opérations sur les fichiers, allocation de mémoire, fonctions sur les chaînes) peuvent passer inaperçues sans contrôle particulier. Un traitement incorrect — ignorer le code de retour, mal interpréter errno, négliger le nettoiement des ressources — conduit à un fonctionnement erroné du programme, à des plantages et à des vulnérabilités.
Un traitement correct des erreurs nécessite une analyse obligatoire des valeurs retournées par les fonctions, l'utilisation d'errno uniquement immédiatement après une erreur, et un affichage informatif des erreurs. Les codes de retour sont préférables pour les fonctions internes — ils permettent une gestion sans effets secondaires globaux. errno est plus souvent utilisé avec des appels système et des fonctions de la bibliothèque standard. Après chaque opération potentiellement dangereuse, le retour est analysé, et l'état global (errno) ne doit pas être écrasé par des appels intermédiaires.
Exemple de code :
#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Erreur : %s ", strerror(errno)); } return f; }
Caractéristiques clés :
Peut-on utiliser errno pour des fonctions utilisateur si l'on souhaite faire remonter les erreurs ?
Non, errno est réservée aux bibliothèques standard et aux appels système. Elle est globale, peut être écrasée à tout moment et n'est pas adaptée pour vos propres fonctions.
Est-il obligatoire de réinitialiser errno avant chaque appel de fonction ?
Non, mais il est recommandé de réinitialiser errno (par exemple à zéro) avant les appels, si l'on prévoit d'analyser les modifications. Toutes les fonctions ne modifient pas errno en cas de succès, mais uniquement en cas d'erreur.
errno = 0; ... appel d'une fonction dangereuse ...
Peut-on faire confiance à errno après n'importe quelle fonction ?
Seulement pour celles qui, selon les normes, définissent explicitement errno en cas d'échec. De nombreuses fonctions de la bibliothèque standard ne touchent pas errno en cas de succès. La documentation est votre amie.
Ouverture d'un fichier sans vérification du résultat, les erreurs ne sont pas analysées, le programme fonctionne incorrectement en l'absence de fichier :
Avantages :
Inconvénients :
Après chaque fonction critique, le résultat est vérifié, en cas d'erreur, un message détaillé avec strerror(errno) est affiché, l'exécution se termine correctement :
Avantages :
Inconvénients :