Home > Blockchain >  How may taking the address of an object influence undefined behavior?
How may taking the address of an object influence undefined behavior?

Time:10-27

On cppreference.com, in the section Implicit conversions, in the subsection "Lvalue conversion", it is noted that

[i]f the lvalue designates an object of automatic storage duration whose address was never taken and if that object was uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined. [emphasis mine]

From that, I undestand that the "act of taking an address" of an object at some point in time may influence in some way whether the undefined behavior happens or not later when this object "is used". If I'm right, then it seems at least unusual.

Am I right? If so, how is that possible? If not, what am I missing?

CodePudding user response:

cppreference.com is deriving this from a rule in the C standard. C 2018 6.3.2 2 says:

If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

So, the reason that taking an address matters is fundamentally because “the C standard says so” rather than because taking the address “does something” in the model of computing.

The reason this rule was added to the C standard was to support some behaviors Hewlett-Packard (HP) desired for its Itanium processor. In that processor, each of certain registers has an associated bit that indicates the register is “uninitialized.” So HP was able to make programs detect and trap in some instances where an object had not been initialized. (This detection does not extend to memory; the bit was only associated with a processor register.)

By saying the behavior is undefined if an uninitialized object is used, the C standard allows a trap to occur but also allows that a trap might not occur. So it allowed HP’s behavior of trapping, it allowed it when HP’s software did not detect the issue and so did not trap, and it allowed other vendors to ignore this and provide whatever value happened to be in a register, as well as other behaviors that might arise from optimization by the compiler.

As for predicating the undefined behavior based on automatic storage duration and not taking the address, I suspect this was a bit of a kludge. It provides a criterion that worked for the parties involved: HP was able to design their compiler to use the “unitialized” feature with their registers, but the rule does not carve out a great deal of object use as undefined behavior. For example, somebody might want to write an algorithm that processes large parts of many arrays en masse, ignoring that a few values “along the edges” of defined regions might be uninitialized. The idea there would be that, in some situations, it is more efficient to do a block of operations and then, at the end, carve away the ones you do not care about. Thus, for these situations, programmers want the code to work with “indeterminate values”—the code will execute, will reach the end of the operations, and will have valid values in the results in cares about, and there will not have been any traps or other undefined behavior arising from the values they did not care about. So limiting the undefined behavior of uninitialized objects to automatic objects whose address is not taken may have provided a boundary that worked for all parties concerned.

CodePudding user response:

If an object had never had its address taken, it could potentially be optimized away. In such cases, attempting to read an uninitialized variable need not yield the same value on multiple reads.

By taking the address of an object, that guarantees that storage is set aside for it which can subsequently be read from. Then the value read will at least be consistent (though not necessarily predictable) assuming it is not a trap representation.

  • Related