Hacker News new | ask | show | jobs
by ncmncm 1839 days ago
Right. Volatile very rarely means what peoole using it imagine it means. It very much does not mean Do What I Mean.

E.g. compilers routinely elide writes to stack variables declared volatile—or even atomic—that they "know" are not aliased. So e.g. if an interrupt routine might look at things in your stack frame, you need to use asm to force it not to fool with writes there. Volatile and atomic don't help you, there, because the stack frame is special.

LTO builds can expose what had been invisible operations in other TUs (".o" files) to the optimizer. So that might demand especial care.

1 comments

To be pedantic, technically they can't elide, reorder or coalesce a accesses to volatile objects any more they can do any other form of I/O, even if it is a local variable whose address is never taken.

Of course how accesses on the abstract machine maps to the actual hardware is implementation defined, although most will document to translate them to plain movs.

And implementations have bugs of course; here [1] gcc removing a volatile access to an otherwise unused volatile parameter is considered a bug, even when the parameter is actually passed via register (in this case I would say the standard is underspecified).

You are absolutely correct regarding non-volatile atomics though.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71793

It is notable that this report is against gcc-5, not assigned, and has not been looked at in five years.

There certainly are people who think volatile should mean something for stack variables, but the compiler people very much Do Not Care. So, by the technical wording of Standards, volatile means the same for all variables, in actual compilers (with certain exceptions) it does not.

Well, Richard Biener certainly count as a compiler person (they are heavily involved with the GCC middle end), and they seem to care, although not enough to fix it as the issue if fairly academical in this case.
This is why volatile function parameters are deprecated in C++20. It's basically nonsensical to begin with.

It sounds like the author of the code expected that the argument would get a memory location on the stack somewhere, but this behavior isn't actually mandated by the standard. If a variable is placed in a register, then "reading" it is a no-op.

Interesting that they are deprecated because volatile locals have specific guarantees with regard to longjmp.