Une assertion qui change le programme
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 4 — Discipline de programmation, validation et test
Énoncé
Ce programme n'affiche pas la même chose selon qu'on le compile avec ou sans -DNDEBUG. Pourquoi, et quelle règle en tirer ?
int appels = 0;
int suivant(void) { appels = appels + 1; return appels; }
int main(void) {
assert(suivant() > 0);
printf("appels = %d\n", appels);
printf("suivant() = %d\n", suivant());
return 0;
}Corrigé
gcc -Wall -Wextra -std=c99 : appels = 1 suivant() = 2
gcc -Wall -Wextra -std=c99 -DNDEBUG : appels = 0 suivant() = 1
Ce qui se passe. assert est une macro, et la définition standard la réduit à rien quand NDEBUG est défini. Ce n'est pas seulement le test qui disparaît : c'est toute l'expression, avec ses effets. Ici, l'appel à suivant() n'a jamais lieu, et le compteur reste à zéro.
La règle : une assertion ne doit contenir aucun effet de bord. Pas d'appel qui modifie un état, pas d'affectation, pas d'incrémentation, pas de lecture sur un flux. On écrit :
int v = suivant(); /* l'effet a lieu, toujours */
assert(v > 0); /* la verification, elle, peut disparaitre */
Et le corollaire, plus important encore. Une assertion vérifie une propriété ; elle ne réalise rien. Sur le même programme :
int racine_entiere(int n) { assert(n >= 0); ... }
sans NDEBUG : Assertion failed: (n >= 0), function racine_entiere,
file afail.c, line 3. code de sortie 134
avec NDEBUG : 0 code de sortie 0
La version livrée ne signale plus rien et rend pour . C'est cohérent avec ce qu'une assertion est — un filet pour le développement, qui suppose la précondition tenue — et c'est incompatible avec l'idée de s'en servir pour valider une entrée. Une donnée qui vient de l'extérieur se teste par un if, qui, lui, ne disparaît jamais.
assert y est une construction du langage, pas une macro : elle lève Assert_failure et n'est retirée que par l'option explicite -noassert. Le piège des effets de bord y est donc moins vicieux — mais la règle reste la même, car -noassert existe.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.