Qu'est-ce que Comportement indéfini (undefined behavior) ?
Comportement sur lequel la norme du C ou du C++ n'impose aucune exigence. En font partie le dépassement de capacité d'un entier signé, la lecture ou l'écriture hors d'un tableau, le déréférencement d'un pointeur NULL, l'utilisation d'une zone libérée et le décalage à gauche d'une valeur négative. Le compilateur peut optimiser en supposant qu'un programme correct n'en contient jamais : un tel code peut fonctionner comme prévu par hasard, ou donner des résultats inattendus, par exemple un test qui disparaît avec certaines options d'optimisation. Il se distingue du comportement défini par l'implémentation, que l'implémentation choisit et documente.
Nom japonais: 未定義動作
« Comportement indéfini (undefined behavior) » apparaît dans 10 questions d'entraînement réparties sur 2 thèmes, dont Bases de la programmation en C, Compilateurs.
Domaine: Bases de la programmation en C
Exemples typiques
On peut citer le dépassement de capacité dans un calcul sur des entiers signés (comme INT_MAX + 1), la lecture ou l'écriture hors d'un tableau, l'utilisation de la valeur d'une variable automatique non initialisée, la lecture ou l'écriture à travers un pointeur NULL ou un pointeur pendant, la double libération d'une même zone, la division d'un entier par 0, ainsi que le décalage d'un nombre de bits supérieur ou égal à la largeur du type et le décalage à gauche d'une valeur négative. Le dépassement d'un entier non signé n'est pas un comportement indéfini : il est défini comme revenant au reste de la division par une puissance de 2.
Questions fréquentes
Quelle différence y a-t-il entre comportement indéfini et comportement défini par l'implémentation ?
Un comportement défini par l'implémentation, comme la taille d'un int, le fait que char soit signé ou non, ou le résultat du décalage à droite d'une valeur négative, est un comportement pour lequel l'implémentation choisit une option et la documente. Un comportement indéfini est un comportement sur lequel la norme n'impose aucune exigence : le résultat peut varier d'un cas à l'autre, même avec la même implémentation. Un programme portable rend explicites les endroits où il s'appuie sur un comportement défini par l'implémentation, et évite tout comportement indéfini.
Un code au comportement indéfini qui fonctionne pose-t-il problème ?
Oui. Même s'il fonctionne par hasard comme prévu dans l'environnement actuel, un changement d'options d'optimisation, de version du compilateur ou du code environnant peut donner un autre résultat. Du point de vue de la sécurité aussi, des comportements indéfinis comme les écritures hors limites peuvent être exploités par des attaquants.