Pourquoi est-il dangereux de se débarrasser des volatiles?

En C ++, volatile est traité de la même manière que const : transmettre un pointeur de données volatiles à une fonction qui ne veut pas que le modificateur volatile déclenche une erreur de compilation.

 int foo(int* bar) { /* snip */ } int main() { volatile int* baz; foo(baz); // error: invalid conversion from 'volatile int*' to 'int*' } 

Pourquoi est-ce dangereux? Il est évident pour le modificateur const que le supprimer peut const correction de const ; mais existe-t-il une “exactitude volatile “? Je ne vois pas en quoi le fait de passer d’un pointeur à une donnée volatile en tant que pointeur vers une donnée non volatile pourrait poser problème.

EDIT Juste pour que vous sachiez pourquoi j’utilisais volatile : beaucoup de la famille de fonctions OSAtomic de Mac OS X (pour les incréments atomiques, les décrémentations, les ajouts, les soustractions, les comparaisons et les permutations, etc.) prennent volatile arguments volatile .

Non seulement le compilateur peut optimiser l’access à distance aux variables non volatiles, il peut également les mettre à jour de manière prédictive / spéculative, à condition que l’exécution séquentielle du programme ne soit pas affectée.

Si des écritures parasites dans votre variable volatile ne cassent pas votre conception, il n’a probablement pas besoin d’être volatile dans aucun contexte.

Par exemple, il est parfaitement légal pour le compilateur C ++ 03 de transformer

 int result; void sum_if_all_positive( std::array ary ) { int sum = 0; result = -1; for( int i = 0; i < N; ++i ) { if (ary[i] < 0) return; sum += ary[i]; } result = sum; } 

dans

 int result; void sum_if_all_positive( std::array ary ) { result = 0; for( int i = 0; i < N; ++i ) { if (ary[i] < 0) { result = -1; return; } result += ary[i]; } } 

(Bien qu'un tel changement fournirait de meilleures performances que l'enregistrement d'une sum uniquement sur quelques architectures avec un access mémoire bon marché et sur très peu de registres. On pense notamment à l'architecture PIC de Microchip.)

Parce que le modificateur volatile signifie que le compilateur doit veiller à effectuer chaque lecture / écriture de l’élément de données volatile exactement comme le spécifie la «machine abstraite» du standard C.

Lorsque le modificateur volatile est supprimé, les access aux données peuvent être optimisés tant que le programme se comporte «comme si» l’access avait eu lieu dans la mesure où le sharepoint vue à thread unique du stream de contrôle du programme était concerné. En d’autres termes, le compilateur peut traiter une donnée non volatile comme si le compilateur et lui seul pouvait voir et modifier la donnée (ce qui est le cas dans la grande majorité des cas).

Le mot clé volatile indique au compilateur que quelque chose d’autre (matériel ou autre thread d’exécution) peut modifier ou voir cet élément de données, de sorte que le compilateur n’est pas autorisé à optimiser les access distants.

Si vous pouviez passer un pointeur sur une donnée volatile à une fonction prenant un pointeur non volatile sans avertissement, la fonction ne verrait peut-être pas de changement dans les données. Si cela vous est égal, vous pourrez peut-être coder une solution de contournement portable et agréable (en fonction de ce que foo() fait avec les données):

 int foo(int* bar) { /* snip */ } int main() { volatile int* baz; int tmp = *baz; foo(&tmp); *baz = tmp; } 

Eh bien, dans foo() le compilateur ne sait plus que baz (ou plus ssortingctement bar ) est volatile et peut donc tenter d’appliquer des optimisations inappropriées.

Le mot-clé volatile signifie que la valeur doit être chargée et stockée à partir de / dans la mémoire à chaque fois.

Considérons le code:

 int foo(int* bar) { while(*bar){ //Do something... } } int main() { volatile int num = 1; volatile int* baz = # //Start a seperate thread to change *baz evenutally... foo(baz); } 

Lorsque le compilateur voit la boucle while et sait que la barre indique toujours 1. Pourquoi devrait-il toujours vérifier chaque fois? Il serait extrêmement inutile de vérifier chaque fois. volatile s’assure que le compilateur effectue cette vérification à chaque fois. Ainsi, lorsque l’autre thread modifie la valeur, la boucle while se termine.

Oui, il existe une “exactitude volatile” .

Il est utilisé pour assurer la sécurité dans le code multithread.