Maison >développement back-end >C++ >Pourquoi l'attribution d'une valeur à une variable complexe provoque-t-elle une boucle infinie dans un programme C, même si cela semble être une action apparemment anodine ?

Pourquoi l'attribution d'une valeur à une variable complexe provoque-t-elle une boucle infinie dans un programme C, même si cela semble être une action apparemment anodine ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-30 04:29:02218parcourir

Why does assigning a value to a complex variable cause an infinite loop in a C   program, even though it appears to be a seemingly innocuous action?

Énigme de compilation C avec comportement de boucle imprévisible

Le code suivant présente un problème de compilation intrigant :

<code class="c++">#include <iostream>
#include <complex>
using namespace std;

int main() {
    complex<int> delta;
    complex<int> mc[4] = {0};

    for(int di = 0; di < 4; di++, delta = mc[di]) {
        cout << di << endl;
    }

    return 0;
}</code>

Contraire à la sortie attendue de "0, 1, 2, 3", le code produit une répétition sans fin de "0, 1, 2, 3, 4, 5, ...". Après enquête, il semble que la comparaison di < 4 ne fonctionne pas correctement, ce qui entraîne une boucle infinie.

La désactivation de l'affectation apparemment anodine delta = mc[di] résout comme par magie le problème, générant le résultat souhaité. Quel est le problème que pose cette simple action ?

Plonger dans un comportement indéfini

La clé pour percer ce mystère réside dans la compréhension d'un comportement indéfini. L'affectation delta = mc[di] déclenche un accès à un tableau hors limites lors de la dernière itération de la boucle. Bien que de nombreux compilateurs puissent supposer qu'aucun comportement indéfini n'est basé sur des stratégies d'optimisation, cette hypothèse est intrinsèquement erronée.

GCC, avec les optimisations activées, peut optimiser de manière agressive la boucle en supposant l'absence de comportement indéfini. Cette optimisation conduit à une inférence erronée selon laquelle di < 4 est toujours vrai, car un accès hors limites au tableau constituerait un comportement indéfini.

En conséquence, la boucle devient infinie, car la condition di < 4 est toujours respecté. Pour éviter cette optimisation erronée, l'indicateur -fno-aggressive-loop-optimizations peut être ajouté à GCC.

Dévoilement du fonctionnement interne du compilateur

Un examen plus approfondi du le code optimisé révèle que le di < 4 check est supprimé et remplacé par une instruction jmp inconditionnelle. Ce comportement s'aligne sur l'hypothèse d'aucun comportement indéfini, ce qui entraîne une boucle infinie.

Contrairement à ce comportement, Clang avec -fsanitize=undefined attraperait ce cas. Cependant, GCC avec le même indicateur ne parvient pas à émettre un avertissement dans ce cas spécifique.

Les périls d'un comportement non défini

Comportement non défini, tel que défini par la norme C, permet des résultats imprévisibles, y compris en ignorant complètement la situation. Un comportement non défini doit être évité à tout prix, car il peut entraîner à la fois des incohérences du compilateur et un comportement d'exécution inattendu.

Pour éviter de tels pièges, les programmeurs doivent s'efforcer d'obtenir un code bien défini qui adhère à la sémantique prévue. Les compilateurs doivent également mettre en œuvre des défenses appropriées pour alerter les développeurs d'un comportement potentiel non défini.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn