Le code de test suivant est correctement en VS avec débogage ou libération, ainsi que dans la GCC. Il suffit également correctement pour la CPI avec débogage, mais pas lorsque l'optimisation activée ( Il est censé s'arrêter à Comme il s'agit d'un programme à filetage unique et em> < Code> Isempty () Code> doit être évalué comme -O2 code>).
tandis que (q.isempty ()) code>. Lorsque
-O2 code> est activé sous ICC (version), il commence à "Dosomethanit" infiniment. P>
vrai code>, je ne peux trouver aucune raison pour laquelle la CPI devrait se comporter de cette manière? Est-ce que quelque chose me manque? P> p>
7 Réponses :
Votre meilleur pari est de prendre l'étape binaire résultante et de dissocier la fonction principale et de voir quel assemblage a été généré. Ne pas dire que vous pourrez voir un bogue, mais vous pouvez voir si quelque chose a été optimisé. P>
Vous ne pouvez pas. Le code ASM est optimisé tout et vous ne pouvez rien voir.
Je ne suis pas sûr de ce que cela signifie. Êtes-vous en train de dire que vous avez dissemblé le binaire résultant et la boucle () a été disparu?
Il ressemble vraiment à un bug. Voici une supposition (assez sauvage) sur quel raisonnement aurait peut-être conduit ...
Après l'allusion, il voit: p> et toute séquence de do rien à plusieurs reprises; faire quelque chose code> peut être traduit simplement "faire quelque chose". Cela tombe si la partie répétée est infinie (comme dans ce cas). Mais peut-être qu'ils ne testent pas leur compilation sur des exemples qui ont intentionnellement une boucle sans fin; -). P> p>
La détection de la boucle ininterrompue intentionnelle est fondamentalement le problème d'arrêt, à la place, ils supposent que, comme il n'a aucun effet secondaire visible, il ne fait rien et est donc inutile pour le programme et peut être supprimé. De toute évidence, il est ou non complétant est un effet SDE visible pour nous, mais pas pour la machine abstraite C / C ++ définie par la norme. Si vous voulez la boucle, vous devez alors dire au compilateur qu'il affecte, effectivement, affecter le programme, pour EXMPLE, en faisant l'une des variables de lecture volatiles.
Je pense que cela a peut-être été votre version de GCC. J'ai compilé votre PROG sous le 4.4.2 et cela a fonctionné exactement comme cela devrait avoir. P>
Toute chance que le code réel que vous avez construit et que vous avez manquait manquait le point-virgule après tandis que (q.isempty ()) code>? Cela entraînerait certainement la prochaine ligne appelée infiniment. P>
1. Il y a un point-virgule 2. Le même résultat avec tout (q.isempty ()) {}, ou tandis que (q.isempty ()) {vrai;}
À qui que ce soit: un vote en bas était vraiment nécessaire? J'ai vu un certain nombre de cas sur l'endroit où le code posté n'était pas le code exact utilisé et où le problème réel avait été laissé ou fixé dans la traduction. Je voulais juste aider à vous assurer que cela n'était pas le résultat d'une erreur simple mais facile à négliger. (Après tout, n'avons-nous pas tous parfois perdu du temps sur un bug en raison de quelque chose comme un point-virgule erroné?)
Parce que le pourrait être optimisé hors de l'existence, tant que Dans le langage C, il s'agit en fait d'un os de contention exceptionnel quant à savoir si une boucle infinie est autorisée à être optimisé de cette manière (je ne sais pas quelle est la situation avec C ++). Autant que je sache, un consensus n'a jamais été atteint sur cette question - les personnes intelligentes et compétentes ont pris des deux côtés. P> p> tandis que (q.isempty ()); code> La boucle ne contient aucune instruction qui peut jamais provoquer un effet secondaire visible de manière externe, toute la boucle est optimisée hors de l'existence. C'est la même raison que:
i code> n'était pas
volatile code> (stocke sur
volatile code> Les objets font partie des effets "visibles externes" d'un programme). P>
Cela pourrait être la raison. Le code suivant fonctionne correctement: statique int A = 0; tandis que (q.isempty ()) {A = A + 1;} mais pas ce qui suit: statique int a = 1; tandis que (q.isempty ()) {a;}
Intéressant. Une boucle infinie sans rien - une bonne opportunité d'optimisation (et c'est compréhensible pourquoi quelqu'un peut être en désaccord).
Une dernière chose: si, alors que (vrai) est utilisé pendant (q.isempty ()), le code fonctionne correctement.
Suma: En ce qui concerne la norme, c'est un comportement correct, car il n'a pas d'effets secondaires visibles, il ne peut pas changer le comportement du programme, non? (Mal - une boucle infinie change le programme, mais puisque la détection si la boucle est infinie ou non, dans le cas général, est essentiellement le problème d'arrêt, il prend la décision de supprimer toujours de telles boucles. Si cela n'est pas souhaitable, alors est à vous, le programmeur, à dire au compilateur qu'il a effectivement des effets secondaires, par exemple en lisant ou en écrivant une varibation volatil ou certains drapeaux spécifiques au compilateur devraient-ils exister)
@Samuel: Notez que dans votre premier exemple, A code> déborde éventuellement, produisant un comportement non défini. Étant donné que l'optimiseur peut supposer que UB ne se produit pas, il peut déduire que
q.isempty () code> doit être faux au début et la boucle entière peut être éliminée.
De côté de côté, cette version de la CPI fait ce que vous voulez. C'est-à-dire qu'il n'appelle jamais dosomething () code>.
La norme C ++ permet d'éliminer les boucles sans effets secondaires, même si elles ne se terminent pas: p>
Il est généralement senti que c'est important d'autoriser la transformation des boucles potentiellement non terminées (par ex. en fusionnant deux boucles qui itérer sur le même potentiel ensemble infini, ou en éliminant un boucle latérale sans effet), même quand ça peut non autrement être justifié dans le cas dans lequel la première boucle jamais se termine. http: //www.open-std. Org / JTC1 / SC22 / WG21 / Documents / Documents / 2007 / N2429.HTM P> blockQuote>
Voir la discussion ici: http://blog.regehr.org/archives/161 p>
Est-ce que cela aide si m_first et m_last sont déclarés «volatiles»? Je n'ai pas accès à la CPI.
Une autre pensée sauvage: Cela a-t-il eu à voir avec le fait que% s n'est pas spécifié avec Printf. printf ("% s", "ne doit pas atteindre ici \ r \ n");?
Connexes: Les compilateurs sont autorisés à éliminer les boucles infinies?
Il vous serait utile d'indiquer la version de la CPI que vous testez et sur quelle plate-forme.
@Samuel: J'aimerais savoir pour ma référence si la «volatilité des membres» a contribué. Cela devrait supprimer tout effet d'optimisation du drapeau
1. Si m_first et m_last sont déclarés "volatiles", il n'y a pas de problème; Si Isempty () est déclaré "volatil", il n'y a pas de problème ni. 2. J'ai utilisé ICC 10 avec vs
Quant à Printf ..., peu importe, vous pouvez faire n'importe quoi dans cette fonction, par exemple, {m_first ++; m_last ++; ...}