On 28.12.16 00.09, Stefan Ram wrote:
> I try to summarize, as I understand it, a programming
> error that was reported at the cppcon:
>
> The essential point seems to have been code like:
>
> int x; if( x )x = 0;
>
> . Assume, you want x to be 0, but in a situation where a
> write access is expensive. So you first check whether it
> happens to already be zero.
>
> Turns out, after this, x might still not be zero!
>
> The cppcon explanation went like this:
>
> The kernel might know that the program reads from uninitialized
> data and return 0 for »x« without actually reading it,
> because it knows that in this case it is free to return any
> value. Later, someone might write into the page that holds x
> and this might cause the page to be created or loaded or
> something and then subsequent read accesses to x will return
> the actual value in the storage which might not be 0.
The basic message is, that uninitialized storage might not even return
/reproducible/ values. Of course, the standard tells nothing about
behavior at UB. In practice it is a academic discussion since it it
almost impossible to find even one existing platform that /does/ return
unreproducible results on uninitialized memory. Only one of the reasons
is that this is always a potential security risk. You might get memory
content that was never intended for your eyes.
> But I believe a C++ programmer might take a more abstract
> point of view: We do not have to know anything about
> pages and kernels! It suffices to know that reading from
> uninitialized storage causes undefined behavior, which
> means that the program from now on can do anything. This
> includes the possibility that consecutive read accesses
> to the same uninitialized object may return different
> values without any intervening write access to this object.
In theory: yes.
But in practice on many platforms taking a conditional branch is by far
more expensive than setting a memory address to zero. So the discussion
is even more academic.
Firstly the branch may discard the CPU pipeline. Secondly the saved
write may cause an additional read cycle. While the write access might
end in the write back cache and is immediately available for read back
the read access is synchronous and may block the pipeline.
Only if writing to physically slow targets (e.g. flash RAM) writes could
be undesired. But at this point we are talking about platform specific
issues and on a certain platform this is likely to be /defined/ behavior.
Conclusion: a programmer should /never/ write crap like this in portable
code.
If on a certain platform it is better to go this way then it should be
up to the optimizer to generate the required code.
Marcel