3 votes

Référence à une variable temporaire - pourquoi le compilateur ne la détecte-t-il pas ?

J'espère qu'il ne s'agit pas d'un doublon, j'ai lu un certain nombre de questions connexes mais personne n'a semblé couvrir ce cas :

 #include <iostream>

int* return_dangling_p()
{
        int x = 1;
        return &x;  // warning: address of local variable 'x' returned
}

void some_func()
{
    int x = 2;
}

int main(int argc, char** argv)
{
    //  UB 1
    int* p = return_dangling_p();
    std::cout << *p;               // 1
    some_func();
    std::cout << *p;               // 2, some_func() wrote over the memory

    // UB 2
    if (true) {
        int x = 3;
        p = &x;     // why does compiler not warn about this?
    }
    std::cout << *p;    // 3
    if (true) {
        int x = 4;    
    }
    std::cout << *p;    // 3, why not 4?

    return 0;
}

Je pensais qu'il s'agissait de deux cas du même comportement indéfini. La sortie est 1233 alors que je m'attendais (naïvement ?) à ce que 1234 .

Ma question est donc la suivante : pourquoi le compilateur ne se plaint-il pas dans le second cas et pourquoi la pile n'est-elle pas réécrite comme dans le cas de 12 ? Ai-je oublié quelque chose ?

(MinGW 4.5.2, -Wall -Wextra -pedantic)

EDIT : Je suis conscient qu'il est inutile de discuter des résultats de l'UB. Ma principale préoccupation était de savoir s'il y a une raison plus profonde pour laquelle l'un est détecté par le compilateur et l'autre non.

3voto

NPE Points 169956

pourquoi le compilateur ne se plaint-il pas dans le second cas ?

Je n'en suis pas certain. Je suppose que c'est possible.

pourquoi la mémoire n'est pas réécrite comme dans le cas de 12

Il s'agit d'un comportement non défini. Tout peut arriver.

Lisez la suite si vous êtes vraiment curieux...

Lorsque je compile votre code tel quel, mon compilateur ( g++ 4.4.3 ) place les deux x variables dans UB 2 à différents endroits de la pile (je l'ai vérifié en regardant le démontage). Ils ne s'opposent donc pas, et votre code imprime également 1233 ici.

Cependant, dès que je prends l'adresse du deuxième x le compilateur décide soudainement de le placer à la même adresse que le premier x La sortie devient donc 1234 .

if (true) {
    int x = 4;    // 3, why not 4?
    &x;
}

C'est ce qui se passe lorsque je compile sans aucune option d'optimisation. Je n'ai pas expérimenté d'optimisations (dans votre version du code, il n'y a pas de raison pour que int x = 4 ne peut pas être complètement optimisée).

Les merveilles du comportement indéfini...

3voto

Oli Charlesworth Points 148744

Je ne sais pas pourquoi le compilateur ne se plaint pas. Je suppose que ce n'est pas un cas d'utilisation très courant, et que les auteurs du compilateur n'ont pas pensé à ajouter un avertissement à ce sujet.

Vous ne pouvez rien déduire d'utile sur le comportement que vous observez lorsque vous invoquez un comportement non défini. Le résultat final aurait pu être 3, 4 ou autre chose.

[Si vous voulez une explication, je vous suggère de regarder l'assembleur que le compilateur a produit. Si je devais deviner, je dirais que le compilateur a optimisé le code final. if (true) { ... } s'éloigner complètement].

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X