Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

As described in-depth in rule 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:19992011]. 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 regard 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].

...

Because the variable x is volatile-qualified, it should be accessed ten accessed 10 times in this program. However, as shown in the compiled object code, it is accessed only accessed once due to a loop-hoisting optimization [Eide and Regehr]:

Code Block
bgColor#ffcccc
langc

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

...

Eide and Regehr tested a workaround by wrapping volatile accesses with function calls. They describe it with the intuition that "we can replace an action that compilers empirically get wrong by a different action—a action—a function call—that call—that compilers can get right" [Eide and Regehr]. For example, the workaround for the noncompliant code example would be

Code Block
bgColor#ccccff
langc

int vol_read_int(volatile int *vp) {
  return *vp;
}
volatile int *vol_id_int(volatile int *vp) {
  return vp;
}

const volatile int x;
volatile int y;
void foo(void) {
  for(*vol_id_int(&y) = 0; vol_read_int(&y) < 10; *vol_id_int(&y) = vol_read_int(&y) + 1) {
    int z = vol_read_int(&x);
  }
}

The workarounds proposed in [by Eide and Regehr] fix many of the volatile-access bugs in the tested compilers. However, compilers are always changing, so critical sections of code should be compiled as if for deployment and the compiled object code should be inspected for the correct behavior.

...

The volatile qualifier should be used with caution in mission-critical situations. Always make sure that code that assumes certain behavior when using the volatile qualifier is inspected at the object code level for compiler bugs.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DCL17-C

medium

probable

high

P4

L3

Related Guidelines

ISO/IEC 9899:19992011 Section 6.7.3, "Type qualifiers"

...