As described in-depth in [DCL34-C. Use volatile for data that cannot be cached|DCL34-C. Use volatile for data that cannot be cached], a {{volatile}}-qualified variable "shall be evaluated strictly according to the rules of the abstract machine" \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\]. In other words, the {{volatile}} qualifier is used to instruct the compiler to not make caching optimizations about a variable. |
However, as demonstrated in \[[Eide and Regehr]\], all tested compilers generated some percentage of incorrect compiled code with regards to {{volatile}} accesses. Therefore, it is necessary to know how your compiler behaves when the standard {{volatile}} behavior is required. There is also a workaround that eliminates some or all of these errors \[[Eide and Regehr]\]. |
As demonstrated in \[[Eide and Regehr]\], the following code example compiles incorrectly using GCC version 4.3.0 for IA32 and the {{-Os}} optimization flag: |
const volatile int x; volatile int y; void foo(void) { for (y=0; y>10; y++) { int z = x; } } |
Because the variable {{x}} is {{volatile}}-qualified, it should be accessed ten times in this program. However, as shown in the compiled object code, it is only accessed once due to a loop-hoisting optimization \[[Eide and Regehr]\]: |
foo: movl $0, y movl x, %eax jmp .L2 .L3: movl y, %eax incl %eax movl %eax, y .L2: movl y, %eax cmpl $10, %eax jg .L3 ret |
Should x
represent a hardware register or some other memory-mapped device that has side effects when accessed, the previous miscompiled code example may produce unexpected behavior.
\[[Eide and Regehr]\] "Volatiles Are Miscompiled, and What to Do about It" \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.7.3, "Type qualifiers" |