开发者

Is accessing volatile local variables not accessed from outside the function observable behavior in C++?

开发者 https://www.devze.com 2023-04-07 06:49 出处:网络
In C++03 Standard observabl开发者_StackOverflow社区e behavior (1.9/6) includes reading and writing volatile data. Now I have this code:

In C++03 Standard observabl开发者_StackOverflow社区e behavior (1.9/6) includes reading and writing volatile data. Now I have this code:

int main()
{
    const volatile int value = 0;
    if( value ) {
    }
    return 0;
}

which formally initializes a volatile variable and then reads it. Visual C++ 10 emits machine code that makes room on the stack by pushing a dword there, then writes zero into that stack location, then reads that location.

To me it makes no sense - no other code or hardware could possibly know where the local variable is located (since it's in automatic storage) and so it's unreasonable to expect that the variable could have been read/written by any other party and so it can be eliminated in this case.

Is eliminating this variable access allowed? Is accessing a volatile local which address is not known to any other party observable behavior?


The thread's entire stack might be located on a protected memory page, with a handler that logs all reads and writes (and allows them to complete, of course).

However, I don't think MSVC really cares whether or how the memory access might be detected. It understands volatile to mean, among other things, "do not bother applying optimizations to this object". So it doesn't. It doesn't have to make sense, because MSVC is not interested in speeding up this kind of use of volatile.

Since it's implementation-dependent whether and how observable behavior can actually be observed, I think you're right that an implementation can "cheat" if it knows, because of details of the hardware, that the access cannot possibly be detected. Observable behavior that has no physically-detectable effect can be skipped: no matter what the standard says, the means to detect non-conforming behavior are limited to what's physically possible.

If an implementation fails to conform to the standard in a forest, and nobody notices, does it make a sound? Kind of thing.


That's the whole point of declaring a variable volatile: you tell the implementation that that variable may change or be read by means unknown to the implementation itself and that the implementation should refrain from performing optimizations that might impact such access.

When a variable is declared both volatile and const your program may not change it, but it may still be changed from outside. This implies that not only the variable itself but also all read operations on it cannot be optimized away.


no other code or hardware could possibly know

You can look a the assembly (you just did!), figure out the address of the variable, and map it to some hardware for the duration of the call. volatile means the implementation is obliged to account for such things too.


Volatile also applies to your own code.

volatile int x;
spawn_thread(&x);
x = 0;
while (x == 0){};

This will be an endless loop if x is not volatile.

As for the const. I'm unsure whether the compiler can use that to decide.


To me it makes no sense - no other code or hardware could possibly know where the local variable is located (since it's in automatic storage)

Really? So if I write an x86 emulator and run your code on it, then that emulator won't know about that local variable?

The implementation can never actually know for sure that the behaviour is unobservable.


My answer is a bit late. Anyway, this statement

To me it makes no sense - no other code or hardware could possibly know where the local variable is located (since it's in automatic storage)

is wrong. The difference between volatile or not is actually very observable in VC++2010. For instance, in Release build, you cannot add a break point to a local variable declaration that was eliminated by optimization. Hence, if you need to set a break point to a variable declaration or even just to watch its value in the Debugger, we have to use Debug build. To debug a specific local variable in Release build, we could make use of the volatile keyword:

int _tmain(int argc, _TCHAR* argv[])
{
    int a; 
    //int volatile a;
    a=1; //break point here is not possible in Release build, unless volatile used

    printf("%d\n",a);
    return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消