C/C++: casting away volatile considered harmful?

前端 未结 3 987
無奈伤痛
無奈伤痛 2020-12-03 17:32

(related to this question Is It Safe to Cast Away volatile?, but not quite the same, as that question relates to a specific instance)

Is there ever a case wh

3条回答
  •  盖世英雄少女心
    2020-12-03 17:53

    With a signature of foo(long *pl), the programmer is declaring that they are not expecting the pointed-to long value to change externally during the execution of foo. Passing a pointer to a long value that is being concurrently modified throughout an invocation might even lead to erroneous behavior if the compiler emits code that dereferences the pointer multiple times due to lack of registers and by it choosing not to store the value of the first dereference on the stack. For example, in:

    void foo(long *pl) {
    
        char *buf = (char *) malloc((size_t) *pl);
    
        // ... busy work ...
    
        // Now zero out buf:
        long l;
        for (l = 0; l < *pl; ++l) {
            buf[l] = 0;
        }
    
        free(buf);
    }
    

    foo could overrun the buffer in the "zero out buf" step if the long value is increased while the busy work is being performed.

    If the foo() function is supposed to atomically increment the long value pointed to by pl, then it would be incorrect for the function to take long *pl and not volatile long *pl because the function clearly requires that accesses of the long value be a sequence point. If foo() only atomically incremented, the function might work, but it would not be correct.

    Two solutions to this problem have already been suggested in comments:

    1. Wrap foo taking long * in an overload taking volatile long *:

      inline void foo(volatile long *pvl) {
          long l = *pvl;
          foo(&l);
          *pvl = l;
      }
      
    2. Change the declaration of foo to void foo(volatile long *pvl).

提交回复
热议问题