C++

Gestion des exceptions en C++

Gestion des exceptions en C++
Il existe trois types d'erreurs logicielles. Ce sont les erreurs de syntaxe, les erreurs de logique et les erreurs d'exécution.

Erreurs de syntaxe

Une expression, une instruction ou une construction mal saisie est une erreur de syntaxe.

Considérez les deux déclarations suivantes :

int arr[] = 1, 2, 3 ; //corriger
int arr = 1, 2, 3 ; //erreur de syntaxe, manquant []

Ce sont des définitions du même tableau. Le premier est correct. Le second manque [], et c'est une erreur de syntaxe. Un programme avec une erreur de syntaxe ne parvient pas à se compiler. La compilation échoue avec un message d'erreur indiquant l'erreur de syntaxe. La bonne chose est qu'une erreur de syntaxe peut toujours être corrigée si le programmeur sait ce qu'il fait.

Erreur de logique

Une erreur logique est une erreur commise par le programmeur lorsqu'un mauvais codage logique est fait. Cela peut être le résultat d'une ignorance du programmeur des fonctionnalités du langage de programmation ou d'une incompréhension de ce que le programme doit faire.

Dans cette situation, le programme est compilé avec succès. Le programme fonctionne bien, mais il produit de mauvais résultats. Une telle erreur peut être due au fait qu'une boucle itère 5 fois alors qu'elle est itérée 10 fois. Il se peut aussi qu'une boucle soit faite inconsciemment pour itérer à l'infini. La seule façon de résoudre ce genre d'erreur est de faire une programmation minutieuse et de tester le programme à fond avant de le remettre au client.

Erreurs d'exécution

Des entrées erronées ou exceptionnelles provoquent des erreurs d'exécution. Dans ce cas, le programme a été compilé avec succès et fonctionne bien dans de nombreuses situations. Dans certaines situations, le programme plante (et s'arrête).

Imaginez que dans un segment de code de programme, 8 doit être divisé par un certain nombre de dénominateurs. Donc, si le numérateur 8 est divisé par le dénominateur 4, la réponse (quotient) serait 2. Cependant, si l'utilisateur saisit 0 comme dénominateur, le programme plantera. La division par 0 n'est pas autorisée en mathématiques, et elle n'est pas non plus autorisée en informatique. La division par zéro doit être évitée dans la programmation. La gestion des exceptions gère les erreurs d'exécution, comme la division par zéro. Le programme suivant montre comment gérer le problème de division par zéro sans utiliser la fonctionnalité d'exception en C++ :

#inclure
en utilisant l'espace de noms std ;
int main()

numérateur entier = 8 ;
dénominateur entier = 2 ;
si (dénominateur != 0 )

résultat int = numérateur/dénominateur ;
cout << result << '\n';

autre

cout << "Division by zero is not permitted!" << '\n';

renvoie 0 ;

La sortie est de 4. Si le dénominateur était 0, la sortie aurait été :

"La division par zéro n'est pas autorisée!"

Le code principal ici est une construction if-else. Si le dénominateur n'est pas 0, la division aura lieu ; si c'est 0, la division n'aura pas lieu. Un message d'erreur sera envoyé à l'utilisateur et le programme continue de s'exécuter sans plantage. Les erreurs d'exécution sont généralement gérées en évitant l'exécution d'un segment de code et en envoyant un message d'erreur à l'utilisateur.

La fonctionnalité d'exception en C++ utilise un try-block pour le if-block et un catch-block pour le else-block pour gérer l'erreur, comme suit :

#inclure
en utilisant l'espace de noms std ;
int main()

numérateur entier = 8 ;
dénominateur entier = 2 ;
essayer

si (dénominateur != 0 )

résultat int = numérateur/dénominateur ;
cout << result << '\n';

autre

lancer 0 ;


attraper (int err)

si (erreur == 0)
cout << "Division by zero is not permitted!" << '\n';

renvoie 0 ;

Notez que l'en-tête try n'a pas d'argument. Notez également que le catch-block, qui est comme une définition de fonction, a un paramètre. Le type de paramètre doit être le même que l'opérande (argument) de l'expression de lancement. L'expression throw est dans le bloc try. Il lance un argument du choix du programmeur qui est lié à l'erreur, et le bloc catch l'attrape. De cette façon, le code du bloc try n'est pas exécuté. Ensuite, le catch-block affiche le message d'erreur.

Cet article explique la gestion des exceptions en C++. Des connaissances de base en C++ sont un prérequis pour que le lecteur comprenne cet article.

Contenu de l'article :

  • Fonction levant une exception
  • Plus d'un bloc de capture pour un bloc d'essai
  • Blocs try/catch imbriqués
  • noexcept-specifier
  • La fonction spéciale std::terminate()
  • Conclusion

Fonction levant une exception :

Une fonction peut également lever une exception comme le fait le bloc try. Le lancer a lieu dans la définition de la fonction. Le programme suivant illustre cela :

#inclure
en utilisant l'espace de noms std ;
void fn(const char* str)

if (islower(str[0]))
lancer 'l';

int main()

essayer

fn("forgeron");

attraper (char ch)

si (ch == 'l')
cout << "Person's name cannot begin in lowercase!" << '\n';

renvoie 0 ;

Notez que cette fois, le bloc try a juste l'appel de fonction. C'est la fonction appelée qui a l'opération de lancer. Le bloc catch intercepte l'exception et la sortie est :

"Le nom de la personne ne peut pas commencer en minuscule!"

Cette fois, le type jeté et attrapé est un char.

Plus d'un bloc de capture pour un bloc d'essai :

Il peut y avoir plus d'un bloc catch pour un bloc try. Imaginez la situation où une entrée peut être l'un des caractères du clavier, mais pas un chiffre ni un alphabet. Dans ce cas, il doit y avoir deux catch-blocks : un pour un entier pour vérifier le chiffre et un pour un char pour vérifier l'alphabet. Le code suivant illustre cela :

#inclure
en utilisant l'espace de noms std ;
entrée char = '*';
int main()

essayer

si (est un chiffre (entrée))
lancer 10 ;
si (isalpha(entrée))
lancer « z » ;

capture (int)

cout << "Digit input is forbidden!" << '\n';

attraper (char)

cout << "Character input is forbidden!" << '\n';

renvoie 0 ;

Il n'y a pas de sortie. Si la valeur d'entrée était un chiffre, e.g., '1', la sortie aurait été :

"La saisie de chiffres est interdite!"

Si la valeur d'entrée était un alphabet, e.g., 'a', la sortie aurait été :

"La saisie de caractères est interdite!"

Notez que dans la liste des paramètres des deux catch-blocks, il n'y a pas de nom d'identifiant. Notez également que dans la définition des deux catch-blocks, les arguments particuliers lancés n'ont pas été vérifiés si leurs valeurs sont exactes ou non.

Ce qui compte pour une capture, c'est le type ; une capture doit correspondre au type d'opérande lancé. La valeur particulière de l'argument (opérande) lancée peut être utilisée pour une vérification supplémentaire si nécessaire.

Plus d'un gestionnaire pour le même type

Il est possible d'avoir deux manipulateurs du même type. Lorsqu'une exception est levée, le contrôle est transféré au gestionnaire le plus proche avec un type correspondant. Le programme suivant illustre cela :

#inclure
en utilisant l'espace de noms std ;
entrée char = '1';
int main()

essayer

si (est un chiffre (entrée))
lancer 10 ;

capture (int)

cout << "Digit input is forbidden!" << '\n';

capture (int)

cout << "Not allowed at all: digit input!" << '\n';

renvoie 0 ;

La sortie est :

"La saisie de chiffres est interdite!"

Blocs try/catch imbriqués :

Les blocs try/catch peuvent être imbriqués. Le programme ci-dessus pour la saisie de caractères non alphanumériques à partir du clavier est répété ici, mais avec le code d'erreur alphabétique imbriqué :

#inclure
en utilisant l'espace de noms std ;
entrée char = '*';
int main()

essayer

si (est un chiffre (entrée))
lancer 10 ;
essayer

si (isalpha(entrée))
lancer « z » ;

attraper (char)

cout << "Character input is forbidden!" << '\n';


capture (int)

cout << "Digit input is forbidden!" << '\n';

renvoie 0 ;

L'erreur alphabétique try/catch-block est imbriquée dans le try-block du code numérique. Le fonctionnement de ce programme et l'opération précédente à partir de laquelle il est copié sont les mêmes.

noexcept-specifier

Considérez la fonction suivante :

void fn(const char* str) noexcept

if (islower(str[0]))
lancer 'l';

Notez le spécificateur 'noexcept' juste après la parenthèse droite de la liste des paramètres de la fonction. Cela signifie que la fonction ne doit pas lever d'exception. Si la fonction lève une exception, comme dans ce cas, elle compilera avec un message d'avertissement mais ne s'exécutera pas. Une tentative d'exécution du programme appellera la fonction spéciale std::terminate(), qui devrait arrêter le programme en douceur au lieu de le laisser littéralement planter.

Le spécificateur noexcept est sous différentes formes. Ce sont les suivants :

tapez func() noexcept; : ne permet pas une expression de lancer
tapez func() noexcept(true); : permet une expression de lancer
tapez func() throw(); : ne permet pas une expression de lancer
tapez func() noexcept(false); : autorise une expression de lancer, qui est facultative
tapez func(); : autorise une expression de lancer, qui est facultative

vrai ou faux entre parenthèses peut être remplacé par une expression qui donne vrai ou faux.

La fonction spéciale std::terminate() :

Si une exception ne peut pas être gérée, elle doit être renvoyée. Dans ce cas, l'expression lancée peut ou non avoir un opérande. La fonction spéciale std::terminate() sera appelée au moment de l'exécution, ce qui devrait arrêter le programme gracieusement au lieu de simplement lui permettre de planter littéralement.

Tapez, compilez et exécutez le programme suivant :

#inclure
en utilisant l'espace de noms std ;
entrée char = '1';
int main()

essayer

si (est un chiffre (entrée))
lancer 10 ;

capture (int)

lancer;

renvoie 0 ;

Après une compilation réussie, le programme s'est terminé sans s'exécuter et le message d'erreur de l'ordinateur de l'auteur est :

"terminate appelé après avoir lancé une instance de 'int'

Abandonné (core sous-évalué) »

Conclusion:

La fonctionnalité d'exception en C++ empêche l'exécution d'un segment de code en fonction d'un type d'entrée. Le programme continue de s'exécuter si nécessaire. La construction d'exception (prévention des erreurs) se compose d'un bloc try et d'un bloc catch. Le bloc try a le segment de code d'intérêt, qui peut être contourné, en fonction de certaines conditions d'entrée. Le bloc try a l'expression throw, qui lance un opérande. Cet opérande est aussi appelé l'exception. Si le type d'opérande et le type du paramètre du bloc catch sont identiques, alors l'exception est interceptée (traitée). Si l'exception n'est pas interceptée, le programme sera terminé, mais restez en sécurité car le segment de code qui devait être exécuté pour donner le mauvais résultat n'a pas été exécuté. La gestion typique des exceptions consiste à contourner le segment de code et à envoyer un message d'erreur à l'utilisateur. Le segment de code est exécuté pour une entrée normale mais contourné pour des entrées erronées.

5 meilleurs jeux d'arcade pour Linux
De nos jours, les ordinateurs sont des machines sérieuses utilisées pour les jeux. Si vous ne pouvez pas obtenir le nouveau score élevé, vous saurez c...
Bataille pour Wesnoth 1.13.6 Développement publié
Bataille pour Wesnoth 1.13.6 publiée le mois dernier, est la sixième version de développement de la 1.13.x series et il apporte un certain nombre d'am...
Comment installer League Of Legends sur Ubuntu 14.04
Si vous êtes fan de League of Legends, alors c'est l'occasion pour vous de tester League of Legends. Notez que LOL est pris en charge sur PlayOnLinux ...