Why is gcc allowed to speculatively load from a struct?

Reading a variable (that was not declared as volatile) is not considered to be a “side effect” as specified by the C standard. So the program is free to read a location and then discard the result, as far as the C standard is concerned.

This is very common. Suppose you request 1 byte of data from a 4 byte integer. The compiler may then read the whole 32 bits if that’s faster (aligned read), and then discard everything but the requested byte. Your example is similar to this but the compiler decided to read the whole struct.

Formally this is found in the behavior of “the abstract machine”, C11 chapter 5.1.2.3. Given that the compiler follows the rules specified there, it is free to do as it pleases. And the only rules listed are regarding volatile objects and sequencing of instructions. Reading a different struct member in a volatile struct would not be ok.

As for the case of allocating too little memory for the whole struct, that’s undefined behavior. Because the memory layout of the struct is usually not for the programmer to decide – for example the compiler is allowed to add padding at the end. If there’s not enough memory allocated, you might end up accessing forbidden memory even though your code only works with the first member of the struct.

Leave a Comment