Que signifient exactement «IB» et «UB»?

J’ai vu les termes “IB” et “UB” utilisés plusieurs fois, en particulier dans le contexte de C ++. J’ai essayé de les googler, mais apparemment, ces combinaisons de deux lettres sont très utiles. : P

Alors, je vous demande … qu’est-ce qu’ils veulent dire, quand on leur dit qu’ils sont une mauvaise chose?

IB: Comportement défini par la mise en œuvre. La norme laisse le choix au compilateur / à la plate-forme en question pour définir le comportement précis, mais nécessite sa définition.

L’utilisation d’un comportement défini par la mise en œuvre peut être utile, mais rend votre code moins portable.

UB: Comportement non défini. 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”, il pourrait théoriquement faire voler les démons hors 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 alerter de manière aléatoire votre code.

Comportement défini par l’implémentation et comportement non défini

Le standard C ++ est très spécifique en ce qui concerne les effets de différentes constructions, et vous devez en particulier toujours être conscient de ces catégories de problèmes :

  • Un comportement non dé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 voler des démons . En ce qui concerne le langage C ++, tout peut arriver. En termes pratiques, cela signifie généralement que vous avez un bug irrécupérable. Si cela se produit, vous ne pouvez pas vraiment faire confiance à votre application (car l’un des effets de ce comportement indéfini pourrait avoir été de détruire la mémoire utilisée par le rest 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 sain et cohérent, mais il n’est pas nécessaire de le documenter .

  • Le comportement défini par l’implémentation est similaire au comportement 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 . En général , il modifie simplement le type d’un pointeur, sans modifier l’adresse, mais le mappage est en fait défini par l’implémentation, de sorte qu’un compilateur pourrait mapper une 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 de savoir s’il s’agit de 2, 4 ou 8 octets, mais il doit être documenté par le compilateur

Mais communément pour tout cela, il vaut mieux les éviter. Lorsque cela est possible, respectez un comportement spécifié à 100% par le standard C ++ lui-même. De cette façon, vous êtes assuré de la portabilité.

Vous devez souvent vous fier à certains comportements définis par l’implémentation. Cela peut être inévitable, mais vous devez toujours faire attention à cela et être conscient que vous comptez sur quelque chose qui peut changer entre différents compilateurs.

Le comportement indéfini, par contre, 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 le comportement défini par l’implémentation – le compilateur doit documenter ce qu’il fait. Effectuer une opération sur une valeur négative est un exemple.

  • UB: comportement indéfini – le compilateur peut faire quoi que ce soit, y compris simplement planter ou donner des résultats imprévisibles. Le fait de déréférencer un pointeur nul entre dans cette catégorie, mais aussi des choses plus subtiles, telles que l’arithmétique du pointeur, qui sort des limites d’un object tableau.

Un autre terme apparenté est «comportement non spécifié». C’est un peu entre les comportements définis et les comportements non définis. pour un comportement non spécifié, le compilateur doit faire quelque chose conformément à la norme, mais le choix du standard dépend exactement du 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 font partie de cette catégorie. Le compilateur peut les exécuter dans l’ordre de son choix et peut 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é).

UB: Comportement non défini

IB: Comportement défini par implémentation

La version courte:

Comportement défini par la mise en œuvre (IB): correctement programmé mais indéterminé *

Comportement non défini (UB): mal programmé (c’est-à-dire un bogue !)

*) “indéterminé” en ce qui concerne le standard de langue, il sera bien sûr déterminé sur toute plate-forme fixe.