Quelqu’un at-il un bon guide pour la conception et le suivi des erreurs / système de contrôle pour C?

Je suis novice dans le domaine du génie logiciel du développement en C; Quelqu’un at-il un bon guide sur la façon de concevoir un système de suivi des erreurs ou de contrôle des erreurs pour un projet C (notamment intégré)? Quelque chose qui parle de suivi des erreurs pour les bibliothèques C serait également utile.

D’après mon expérience, les stratégies ici tombent dans quelques camps.

  • Utilisation de variables globales ala errno . En gros, toute fonction peut stocker un code d’erreur dans la variable globale. Ainsi, après l’exécution de la fonction, vous pouvez lire le code d’erreur pour voir s’il est correctement exécuté. Lorsque vous travaillez dans un environnement multithread, il y a des problèmes évidents. Bien qu’il semble que POSIX.1c spécifie une solution à ce problème.

  • Demandez à chaque fonction de renvoyer un code d’erreur. Par exemple:

    RESULT_CODE my_function(int param1, int param2); RESULT_CODE error_code = my_function(10, 2); 

Le problème avec cette approche est que vous perdez votre capacité à renvoyer directement les valeurs de la fonction.

  • Chaque fonction a un paramètre supplémentaire qui stocke le code de résultat. Par exemple:

     void my_function(int param1, int param2, RESULT_CODE *err); RESULT_CODE error_code; my_function(10, 2, &error_code); switch (error_code) { case RESULT_OK: // all OK break; case RESULT_NO_MEM: // out of memory break; // etc... } 

J’ai vu cette approche utilisée avec succès dans les RTOS commerciaux et je la préfère personnellement car je la trouve la moins ressortingctive. Le seul inconvénient potentiel est que vous devez déclarer explicitement une variable pour stocker le code d’erreur, même si vous ne vous souciez pas du résultat. Dans un certain sens, j’aime bien cette exigence car elle vous oblige à réfléchir constamment à la manière dont les erreurs seront traitées.

Ces liens peuvent être utiles:

  • Errors: errno dans les programmes UNIX – Utilisation du mécanisme d’erreur standard
  • Rapport d’erreur (La bibliothèque GNU C)

Ce sont les choses de base que vous devrez définir:

  • Niveaux de trace (par exemple, débogage, alertes, avertissements, informations, critiques, etc.). Vous devez également définir un niveau de trace actuel. Ainsi, si le niveau de trace actuel est INFO, tous les messages dont le niveau de trace est supérieur aux informations sont imprimés. Si le niveau de trace actuel est critique, seuls les messages critiques seront imprimés.
 enum _TraceLevelType { INFO = 0, DEBUG, WARNING, ERROR, CRITICAL } TraceLevelType; 
  • Codes d’erreur, je pense que le meilleur moyen est d’avoir un gros enum. Quelque chose comme ça:
 enum _ErrorType { //Internal errors 0-100 APPLICATION_FAILURE = 0, ... MEMORY_FAULT, //UI ERRORS 101-200 INVALID_OPTION_SELECTED = 101, .... ... }ErrorType; 
  • Une queue de messages, vous devriez avoir un mécanisme où tout le monde pourrait envoyer des messages et ces messages sont correctement mis en queue. Puisque vous travaillez sur des systèmes embarqués, cela est essentiel. Vous ne voulez pas passer du temps à imprimer des messages de débogage sur un système d’exploitation en temps réel. Le thread qui gère les codes d’erreur doit donc avoir une priorité très basse et tous les messages reçus doivent être envoyés dans une queue. Ainsi, lorsque le planificateur décide de l’appeler, vous envoyez les printfs à la console ou à la sortie de votre choix.

Donc, votre méthode d’erreur sera quelque chose comme ça:

 TraceError(TraceLevelType traceLevel, ErrorType errorType, char *msg) { if(CURRENT_TRACE_LEVEL <= traceLevel) /* Ignore message */ else /*Queue the Message*/ } 

Vous pourriez aussi avoir plus de parameters pour indiquer quel module envoie l’erreur, mais je pense que c’est tout.