0
votes

Lors de la diffusion d'un const vers un pointeur non-Const en C ++ 2017 et de la modifier, où le compilateur stocke-t-il les deux valeurs?

dans Visual C ++ 2017, lors de l'expérimentation de ce qui se passe lorsque vous cassez les règles, j'ai constaté que si je jette un const Int à un int *, puis réaffectez une valeur à l'INT *, le débogueur changera la valeur de Le const, mais l'exécution d'exécution ne sera pas.

Cela se produit si je l'exécute ou non dans le mode de débogage ou comme exécutable libéré. Je suis au courant que ce soit indéfini, mais je cherche une idée de savoir où ces valeurs sont détenues, car elles semblent être des emplacements identiques. xxx

où sont stockées les deux valeurs stockées ? Ceci est comme avoir un seau qui est simultanément rempli de deux liquides différents.

Je suis conscient que c'est un comportement indéfini, mais je me demandais si quelqu'un pouvait éclairer ce qui se passe, en interne.


8 commentaires

Le compilateur ne choisira pas une adresse différente à cause du casting. La coulée explicite détend que les stratégies de contrôle de type, et vous vous retrouvez probablement avec comportement indéfini .


Je vote pour fermer cette question comme étant hors sujet, car demandez à une grave idée fausse à quel point le casting fonctionne en C ++.


Je suppose que le compilateur optimise le code en remplaçant toutes les références à j avec la valeur littérale 200, même pour les constructions "debug". Comme il est censé être constant, cela peut (devrait) faire cela. Je ne sais pas pourquoi le débogueur se comporte différemment, cependant.


@ πάνταῥεῖῖ ou, vous pourriez expliquer ma mauvaise idée, ce qui contribuerait probablement à répondre à la question. C'était à ma compréhension que le const INT pointait à une tache de la mémoire similaire à une variable, et je l'ai référencée et la modifiait sans le compilateur exécutant la restriction de la const. Où est-ce que je me trompe dans cette compréhension? Les constitus sont-ils conservés dans une table quelque part séparément?


Ne vous attendez pas à trouver un sens dans le domaine du comportement indéfini. Mais vous pouvez utiliser les types volatile pour vous assurer que le compilateur ne cache aucune valeur.


@JPCHERRY "Les constitus sont conservés dans une table quelque part séparément?" Non, ils ne sont pas.


Il serait intéressant d'inspecter le code de la machine.


@ALTERIGEL: De nombreuses formes de programmation seraient impossibles sans s'appuyer sur des implémentations "Traitement de nombreuses constructions" dans une caractéristique de mode documentée de l'environnement ". La situation particulière décrite dans ce poste est une forme de comportement critique non défini dans lequel relativement peu de mises en œuvre, voire pourraient, garantir tout ce qui est utile, mais de nombreuses tâches seraient impossibles sans trouver beaucoup de sens dans la manière dont les implémentations adaptées à la programmation de bas niveau Constructions de processus lorsque la norme impose aucune exigence.


3 Réponses :


1
votes

La prémisse est défectueuse. Le débogueur fonctionne selon les mêmes règles C ++ 17, afin que cela puisse également supposer qu'il n'y a pas de comportement indéfini. Cela signifie qu'il peut vérifier le code source et savoir j == 100 . Il n'y a aucune raison pour vérifier la valeur d'exécution.


2 commentaires

Sauvez-vous ou savez-vous que ce débogueur particulier fonctionne comme vous dites?


@ BESC: Eh bien, ce débogueur particulier ne directement vérifier le code source, il dispose de ces informations dans le fichier PDB.



0
votes

Si un objet est dans const Stockage, un compilateur peut à sa loisirs, remplacez-le avec deux objets ou plus qui ont le même contenu si cela peut dire que les adresses ne sont jamais comparées. Un compilateur ne serait généralement pas capable de le faire si les deux adresses d'objets sont exposées au monde extérieur, mais peuvent le faire dans des cas où un objet est exposé, mais l'autre (s) ne le sont pas.

considère, par exemple: xxx

Traitement du compilateur Test serait capable de voir que la valeur de heyytr n'est jamais exposée au code extérieur dans Toute façon, et sur certaines plates-formes pourraient bénéficier de la fonction utilise sa propre copie de la chaîne. Sur une plate-forme où les adresses sont de 64 bits, si test n'inclut pas sa propre copie de la chaîne, alors huit octets auraient besoin de contenir l'adresse de hey . Les quatre octets nécessaires pour stocker une copie supplémentaire de la chaîne coûteraient moins cher que les huit octets nécessaires pour contenir l'adresse.

Il existe quelques situations où la norme offre des garanties plus fortes que les programmeurs ont généralement besoin. Par exemple, donné: xxx

sauf si un programme ne se comparait pas à comparer foo (ou une adresse dérivée de celle-ci) avec bar (également), en utilisant le même stockage pour les deux objets permettrait d'économiser 16 octets sans affecter la sémantique du programme. La norme ne fournit toutefois aucun moyen par lequel un programmeur pourrait indiquer que le code ne comparera pas ces adresses ou ne serait pas affectée négativement si elles se comparent à comparer égale, donc un compilateur ne peut que faire de telles substitutions dans les cas où elle peut Dites que l'adresse d'un objet substitué ne sera pas exposée au code qui pourrait effectuer de telles comparaisons.


0 commentaires

0
votes

Eh bien, il suffit de regarder l'assemblage généré ...

    const int j = 100;
    //int *q = &j; //Compiler disallows
    int *q = (int*)&j; //By some magic, now allowed
    *q = 300; //After this line, j = 300 in debugger
    cout << "j = " << j << endl; //300 in debugger, 100 in console
000C101D  lea         rdx,[string "j = " (07FF72FAC3298h)]  
000C1024  mov         rcx,qword ptr [__imp_std::cout (07FF72FAC30A8h)]  
000C102B  call        std::operator<<<std::char_traits<char> > (07FF72FAC1110h)  
000C1030  mov         edx,64h  
000C1035  mov         rcx,rax  
000C1038  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF72FAC30A0h)]  
000C103E  lea         rdx,[std::endl<char,std::char_traits<char> > (07FF72FAC12E0h)]  
000C1045  mov         rcx,rax  
000C1048  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF72FAC3098h)]  
    //^ What is happening here? Where are the two values stored?
    cout << "*q = " << *q << endl; //300 in both
000C104E  lea         rdx,[string "*q = " (07FF72FAC32A0h)]  
000C1055  mov         rcx,qword ptr [__imp_std::cout (07FF72FAC30A8h)]  
000C105C  call        std::operator<<<std::char_traits<char> > (07FF72FAC1110h)  
000C1061  mov         edx,12Ch  
000C1066  mov         rcx,rax  
000C1069  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF72FAC30A0h)]  
000C106F  lea         rdx,[std::endl<char,std::char_traits<char> > (07FF72FAC12E0h)]  
000C1076  mov         rcx,rax  
000C1079  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF72FAC3098h)]  


0 commentaires