J'ai vu les termes "IB" et "UB" utilisés plusieurs fois, en particulier dans le contexte de C++. J'ai essayé de les rechercher sur Google, mais apparemment, ces combinaisons de deux lettres sont très utiles. : P
Alors, je vous demande ... qu'est-ce que ça veut dire, quand on dit que c'est une mauvaise chose?
IB: Comportement défini par l'implémentation. La norme laisse au compilateur/à la plate-forme particulière le soin de définir le comportement précis, mais requiert sa définition.
L'utilisation d'un comportement défini par l'implémentation peut être utile, mais rend votre code moins portable.
B: Undefined Behavior. La norme ne spécifie pas comment un programme invoquant un comportement non défini doit se comporter. Également connu sous le nom de "démons nasaux" car il pourrait théoriquement faire sortir les démons de votre nez.
Utiliser un comportement non défini est presque toujours une mauvaise idée. Même si cela semble fonctionner parfois, toute modification de l'environnement, du compilateur ou de la plate-forme peut casser de manière aléatoire votre code.
Comportement défini par l'implémentation et comportement indéfini
Le standard C++ est très spécifique sur les effets de diverses constructions, et en particulier, vous devez toujours être conscient de ces catégories de trouble:
Un comportement indéfini signifie qu'il n'y a absolument aucune garantie donnée. Le code pourrait fonctionner, ou il pourrait mettre le feu à votre disque dur ou faire sortir les démons de votre nez . En ce qui concerne le langage C++, absolument tout peut arriver. En termes pratiques, cela signifie généralement que vous avez un bogue irrécupérable. Si cela se produit, vous ne pouvez pas vraiment faire confiance à n'importe quoi à propos de votre application (car l'un des effets de ce comportement non défini pourrait simplement avoir été de gâcher la mémoire utilisée par le reste de votre application) . Il n'est pas nécessaire d'être cohérent, donc exécuter le programme deux fois peut donner des résultats différents. Cela peut dépendre des phases de la lune, de la couleur de la chemise que vous portez ou de toute autre chose.
Un comportement non spécifié signifie que le programme doit faire quelque chose de sensé et cohérent, mais il n'est pas nécessaire de document cela.
Le comportement défini par l'implémentation est similaire à non spécifié, mais doit également être documenté par les rédacteurs du compilateur. Un exemple de ceci est le résultat d'un reinterpret_cast
. généralement, il change simplement le type d'un pointeur, sans modifier l'adresse, mais le mappage est en fait défini par l'implémentation, donc un compilateur pourrait mapper à un adresse complètement différente, à condition de documenter ce choix. Un autre exemple est la taille d'un int. Le standard C++ ne se soucie pas s'il est de 2, 4 ou 8 octets, mais il doit être documenté par le compilateur
Mais commun à tous ces éléments, il vaut mieux les éviter. Lorsque cela est possible, respectez le comportement spécifié à 100% par la norme C++ elle-même. De cette façon, vous êtes assuré de la portabilité.
Vous devez également souvent vous fier à certains comportements définis par l'implémentation. Cela peut être inévitable, mais vous devez toujours y faire attention et être conscient que vous comptez sur quelque chose qui peut changer entre différents compilateurs.
En revanche, un comportement indéfini doit toujours être évité. En général, vous devez simplement supposer que cela fait exploser votre programme d'une manière ou d'une autre.
IB: est un comportement défini par l'implémentation - le compilateur doit documenter ce qu'il fait. Exécution d'un >>
l'opération sur une valeur négative en est un exemple.
UB: comportement indéfini - le compilateur peut faire n'importe quoi, y compris simplement planter ou donner des résultats imprévisibles. Le déréférencement d'un pointeur nul entre dans cette catégorie, mais aussi des choses plus subtiles comme l'arithmétique du pointeur qui sort des limites d'un objet tableau.
Un autre terme connexe est "comportement non spécifié". C'est en quelque sorte entre les comportements définis et non définis par l'implémentation. pour un comportement non spécifié, le compilateur doit faire quelque chose conformément à la norme, mais exactement quels choix la norme lui donne appartient au compilateur et n'a pas besoin d'être défini (ou même cohérent). Des choses comme l'ordre d'évaluation des sous-expressions entrent dans cette catégorie. Le compilateur peut les exécuter dans l'ordre qu'il souhaite et pourrait le faire différemment dans différentes versions ou même dans différentes exécutions de la même version (peu probable, mais autorisé).
La version courte:
Comportement défini par l'implémentation (IB): Correctement programmé mais indéterminé *
Comportement indéfini (UB): Mal programmé (c'est-à-dire un bug !)
*) "indéterminé" en ce qui concerne le standard linguistique, il sera bien entendu déterminé sur toute plateforme fixe.