informatique (MP2I/MPI) · Chapitre 4 · Exercice de TD
Assertion, ou traitement d'erreur
Discipline de programmation, validation et test · niveau 2
Énoncé
Pour chacune de ces six situations, dire s'il faut une assertion ou un traitement d'erreur, et pourquoi.
- Une fonction interne reçoit un indice négatif, alors que son unique appelant le calcule par une boucle bornée.
- L'utilisateur saisit
abclà où on attend un entier. - Le fichier de configuration n'existe pas.
mallocrendNULL.- Une fonction de tri rend un tableau qui n'est pas trié.
- Le dénominateur d'une division vaut zéro, et il vient d'une mesure lue sur un capteur.
Corrigé
La règle de partage, en une phrase : une assertion dit « ceci ne peut pas arriver, et si cela arrive mon programme est faux » ; un traitement d'erreur dit « ceci peut arriver, et voici ce que je fais alors ». La question à se poser n'est donc pas « est-ce grave ? » mais « qui peut être fautif ? ».
| Quoi | Pourquoi | |
|---|---|---|
| 1 | assertion | La faute serait celle du programmeur : l'appelant garantit l'indice. Rien d'extérieur ne peut le violer. |
| 2 | traitement | Une saisie est une donnée du monde extérieur. Elle est prévue, on la redemande ou l'on refuse proprement. |
| 3 | traitement | Idem : un fichier absent est un état normal du système. On crée une configuration par défaut, ou l'on quitte avec un message. |
| 4 | traitement | L'épuisement de la mémoire ne dépend pas de la correction du code. On rend NULL en libérant ce qu'on a déjà pris (problème 1.1). |
| 5 | assertion | C'est un défaut du tri, c'est-à-dire du programmeur. En pratique, une telle assertion se met dans les tests, pas en production. |
| 6 | traitement | Un capteur peut rendre n'importe quoi : c'est une entrée. On définit et on documente le comportement — valeur précédente conservée, mesure ignorée, alarme. |
Le cas 6 mérite d'être opposé au cas 1, car la situation numérique est identique : un zéro là où l'on attendait autre chose. Ce qui diffère est l'origine de la donnée. Un même test, écrit assert(d != 0) ou if (d == 0) { ... }, sera juste dans un cas et faux dans l'autre.
gcc -DNDEBUG supprime tous les assert. Employer une assertion pour valider une donnée d'utilisateur revient donc à ne rien valider du tout dans la version livrée — et c'est exactement la situation qui produit les failles dont parle l'introduction de ce chapitre. L'exercice 4.6 le mesure.