RACE CONDITION -> Ordre des variables non respecté lors de la compilation "Optimization: Minimize Size (/O1)"
Bonjour,
J'ai rencontré récement un problème avec Visual Studio.
En effet, quand je compile ma source, Visual ne respecte pas l'ordre des variables, ce qui me pose problème en multithreading (race condition).
Voici un simple exemple :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| BOOL FuncTest()
{
static BOOLEAN bTestEmpty = TRUE;
static BOOL bTest;
DWORD dwTest;
if (bTestEmpty == TRUE)
{
/* ICI, du code qui utilise dwTest ... */
bTest = ((dwTest) ? TRUE : FALSE); // Remplie bTest avec la bonne valeur
bTestEmpty = FALSE; // Met bTestEmpty sur FALSE pour dire que le test a déjà été fait
}
return (bTest);
}; |
Donc logiquement, si l'ordre est respecté, c'est à dire que "bTest" est remplie avant que "bTestEmpty" soit mis sur FALSE, ça ne pose aucun problème pour le multithreading.
Mais quand je regarde sous OllyDebug, je vois ça:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 10010D0F CMP BYTE PTR DS:[1002E206],1 // if (bTestEmpty == TRUE)
10010D16 JNE SHORT 10010D46
// ICI
// DU CODE QUI UTILISE dwTest
10010D34 CMP DWORD PTR SS:[ESP],EAX
10010D37 MOV BYTE PTR DS:[1002E206],0 // bTestEmpty = FALSE;
10010D3E SETNE AL
10010D41 MOV DWORD PTR DS:[10032784],EAX // bTest = ((dwTest) ? TRUE : FALSE);
10010D46 MOV EAX,DWORD PTR DS:[10032784] // return (bTest);
10010D4B POP ECX
10010D4C RETN |
On voit très bien que bTestEmpty est mis sur FALSE avant de remplir bTest.
Ce qui produit une Race Condition (Si plusieurs threads utilisent la fonction au même moment).
Je compile mon code avec "Optimization: Minimize Size (/O1)"
Donc ça doit être pour ça que l'ordre des variables n'est pas respecté.
Si je rajoute #pragma optimize("", off) avant et #pragma optimize("", on) après ma fonction, ça corrige le problème :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 10010D12 MOVZX EAX,BYTE PTR DS:[1002E206] // if (bTestEmpty == TRUE)
10010D19 CMP EAX,1
10010D1C JNE SHORT 10010D4D
// ICI
// DU CODE QUI UTILISE dwTest
10010D41 MOV DWORD PTR DS:[10032784],EAX // bTest = ((dwTest) ? TRUE : FALSE);
10010D46 MOV BYTE PTR DS:[1002E206],0 // bTestEmpty = FALSE;
10010D4D MOV EAX,DWORD PTR DS:[10032784] // return (bTest);
10010D52 LEAVE
10010D53 RETN |
Mais alors les optimisations pour la taille de ma fonction ne sont pas faites.
Alors oui, ce n'est pas grave si je désactive les optimisations pour cette fonction mais j'ai plusieurs fonctions ou je fais se genre de manip.
Donc ma question est :
Il y a t'il une solution pour que l'ordre des variables soient respectée tout en laissant les optimisations activées ?
Merci d'avance !
A+