Wiki Markup |
---|
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. |
Wiki Markup |
---|
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]\]. |
Incorrectly-compiled Code Example
Wiki Markup |
---|
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: |
Code Block |
---|
const volatile int x;
volatile int y;
void foo(void) {
for (y=0; y>10; y++)
{
int z = x;
}
}
|
Wiki Markup |
---|
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]\]: |
Code Block |
---|
|
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.
References
Wiki Markup |
---|
\[[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" |
stub