Est-ce une erreur de compilateur dans Visual Studio 2010?
-
28-10-2019 - |
Question
J'ai un bug dans ce conditionnel:
while(CurrentObserverPathPointDisplacement > lengthToNextPoint && CurrentObserverPathPointIndex < (PathSize - 1) )
{
CurrentObserverPathPointIndex = CurrentObserverPathPointIndex + 1;
CurrentObserverPathPointDisplacement -= lengthToNextPoint;
lengthToNextPoint = (CurrentObserverPath->pathPoints[min((PathSize - 1),CurrentObserverPathPointIndex + 1)] - CurrentObserverPath->pathPoints[CurrentObserverPathPointIndex]).length();
}
Il semble rester coincé dans une boucle infinie en mode libération. Fonctionne bien en mode débogage, ou plus interstoutant lorsque je mets une impression de débogage sur la dernière ligne
OutputInDebug("Here");
Voici l'assemblage généré pour le conditionnel lui-même:
while(CurrentObserverPathPointDisplacement > lengthToNextPoint && CurrentObserverPathPointIndex < (PathSize - 1) )
00F074CF fcom qword ptr [dist]
00F074D2 fnstsw ax
00F074D4 test ah,5
00F074D7 jp ModelViewData::moveCameraAndCenterOnXYPlaneForwardBackward+27Eh (0F0753Eh)
00F074D9 mov eax,dword ptr [dontRotate]
00F074DC cmp eax,ebx
00F074DE jge ModelViewData::moveCameraAndCenterOnXYPlaneForwardBackward+27Eh (0F0753Eh)
{
Vous pouvez voir que pour la deuxième condition, il semble déplacer la valeur de «dontrotate», un paramètre de fonction de type bool, dans EAX, puis comparer avec lui, mais Dontrotate est utilisé nulle part près de ce morceau de code.
Je comprends que cela peut être un peu peu de données, mais cela semble être une erreur évidente du compilateur personnellement. Mais malheureusement, je ne sais pas comment le distiller à un problème autonome pour produire un rapport de bogue.
Edit: pas les décélérations réelles, mais les types:
double CurrentObserverPathPointDisplacement;
double lengthToNextPoint;
int CurrentObserverPathPointIndex;
int PathSize;
vector<vector3<double>> CurrentObserverPath::pathPoints;
Edit2:
Une fois que j'ai ajouté l'instruction d'impression de débogage à la fin du temps, c'est l'assemblée qui est générée, qui n'exprime plus le bogue:
while(CurrentObserverPathPointDisplacement > lengthToNextPoint && CurrentObserverPathPointIndex < (PathSize - 1) )
00B1751E fcom qword ptr [esi+208h]
00B17524 fnstsw ax
00B17526 test ah,5
00B17529 jp ModelViewData::moveCameraAndCenterOnXYPlaneForwardBackward+2D6h (0B175A6h)
00B1752B mov eax,dword ptr [esi+200h]
00B17531 cmp eax,ebx
00B17533 jge ModelViewData::moveCameraAndCenterOnXYPlaneForwardBackward+2D6h (0B175A6h)
{
La solution
Ici:
while(/* foo */ && CurrentObserverPathPointIndex < (PathSize - 1) )
{
CurrentObserverPathPointIndex = CurrentObserverPathPointIndex + 1;
Puisque c'est le seul point (sauf si min
fait quelque chose de vraiment méchant) dans la boucle où CurrentObserverPathPointIndex
est changé et les deux CurrentObserverPathPointIndex
et PathSize
sont signés entiers de la même taille (et PathSize
est suffisamment petit pour exclure les problèmes de promotion entière), le point de triage flottant restant n'est pas pertinent. La boucle doit éventuellement se terminer (cela peut prendre beaucoup de temps si la valeur initiale de CurrentOvserverPathPointIndex
est petit par rapport à PathSize
, pourtant).
Cela ne permet qu'une seule conclusion; Si le compilateur génère du code qui ne se termine pas (jamais), le compilateur est faux.
Autres conseils
On dirait PathSize
ne change pas dans la boucle, donc le compilateur peut calculer PathSize - 1
Avant de boucler et de coïncidrement utiliser le même emplacement de mémoire que dontRotate
, Quoique ce soit.
Plus important encore, combien d'éléments y a-t-il CurrentObserverPath->pathPoints
?
Votre condition de boucle comprend ce test:
CurrentObserverPathPointIndex < (PathSize - 1)
À l'intérieur de votre boucle se trouve cette affectation:
CurrentObserverPathPointIndex = CurrentObserverPathPointIndex + 1;
suivi par cet indice supplémentaire incrémenté:
[min((PathSize - 1),CurrentObserverPathPointIndex + 1)]
Peut-être que votre code semblait fonctionner en mode débogage parce que le comportement non défini aléatoire semblait fonctionner?