Maison >développement back-end >C++ >Les compilateurs C peuvent-ils supposer que la représentation numérique d'un booléen est uniquement 0 ou 1, et cela conduit-il à un comportement indéfini ?
Optimisation du compilateur et comportement non défini : le C autorise-t-il certaines hypothèses sur les bools ?
Introduction
Cet article examine si le standard C permet aux compilateurs d'assumer certaines représentations numériques pour les booléens et si de telles les hypothèses peuvent entraîner des conséquences telles que des plantages de programme.
Le problème
Un programmeur a rencontré un plantage de programme alors qu'il utilisait une valeur bool non initialisée dans une fonction qui sérialisait un booléen en une chaîne. Étonnamment, le crash s'est produit uniquement sur une plate-forme spécifique utilisant un compilateur spécifique avec l'optimisation activée.
Le code problématique :
void Serialize(bool boolValue) { const char* whichString = boolValue ? "true" : "false"; const size_t len = strlen(whichString); memcpy(destBuffer, whichString, len); }
Lorsque le code est exécuté avec Clang 5.0.0 et optimisation ( -O2), il peut planter. Ce comportement est dû à la déduction de l'optimiseur selon laquelle les chaînes "true" et "false" ne diffèrent que par leur longueur de 1. Au lieu de calculer la longueur réelle, il utilise la valeur de boolValue, en supposant qu'elle est 0 ou 1.
const size_t len = strlen(whichString); // original code const size_t len = 5 - boolValue; // clang optimization
Question : Considérations standard
L'article pose la question : la norme C est-elle permettre à un compilateur de supposer qu'un booléen ne peut avoir qu'une représentation numérique interne de « 0 » ou « 1 » et de l'utiliser de cette manière ? Ou s'agit-il d'un cas de comportement défini par l'implémentation où l'implémentation a supposé que tous ses booléens ne contiendraient que 0 ou 1, et toute autre valeur est un territoire de comportement non défini ?
Réponse : conformité standard
Selon l'auteur, ISO C permet (mais n'oblige pas) les implémentations de faire ce choix. ISO C ne précise pas quelle est la représentation interne d'un bool, permettant aux implémentations de faire leurs propres hypothèses.
Comportement d'optimisation du compilateur
System V ABI : Pour les plateformes utilisant l'ABI System V, couramment utilisé sur les systèmes x86-64, un argument booléen passé à une fonction est représenté par le modèles de bits : 0 = faux et 1 = vrai dans les 8 bits de poids faible du registre. En mémoire, bool est un type de 1 octet qui doit avoir une valeur entière de 0 ou 1.
Cette décision ABI permet au compilateur de tirer parti des optimisations, telles que supposer 0 ou 1 pour bool et exécuter au niveau du bit opérations au lieu de conversions de types coûteuses. Dans l'exemple fourni, l'optimiseur a exploité ce comportement pour optimiser strlen(whichString) à 5U - boolValue.
Autres implémentations et hypothèses :
Bien que l'ABI System V soit largement utilisé, d'autres implémentations pourraient faire des hypothèses différentes. Par exemple, ils pourraient considérer 0 = faux et toute valeur non nulle = vrai. Dans un tel scénario, le compilateur pourrait ne pas générer de code qui plante pour des valeurs booléennes non initialisées, mais cela pourrait quand même être considéré comme un comportement non défini.
Les dangers des plantages de programme
Bien que le standard C autorise de telles optimisations, il est important de noter que les programmes rencontrant un comportement indéfini sont considérés comme totalement indéfinis pendant toute leur existence. Cela signifie qu'un crash peut se produire même si le comportement non défini est rencontré dans une fonction qui n'est jamais réellement appelée.
Bonnes pratiques et évitement des comportements non définis
Les compilateurs deviennent de plus en plus agressifs dans l'optimisation du code, assumant des comportements basés sur leur compréhension interne de l'implémentation. Il est crucial pour les programmeurs d'éviter de se fier à des hypothèses d'implémentation et de s'assurer que leur code est un C valide sans supposer qu'il se comportera comme un langage d'assemblage portable.
Pour éviter les problèmes, les programmeurs doivent suivre ces bonnes pratiques :
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!