6 ms·
As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value
by tspiteri 7y ago
As far as I know (and I could be wrong), reading uninitialized memory in C is not UB, but gives an indeterminate value, which may be either an unspecified value or a trap representation. If it is a trap representation, accessing it is indeed UB, but if all possible values of your memory are valid, e.g. if you have an unpadded integer where every bit representation means something valid, then it is not UB, though it is still an unspecified value which does not even have to be consistent: you could get different values when reading the same uninitialized location twice.
Edit: Some excerpts from the C standard:
6.7.8 Initialization
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
3.17.2 indeterminate value
either an unspecified value or a trap representation
3.17.3 unspecified value
valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance
6.2.6 Representation of types
6.2.6.1 General
5 Certain object representations need not represent a value of the object type. … Such a representation is called a trap representation.
- lmkg 7y agoNot a C expert, just reading what I can find online: This page says value is indeterminate, which is either unspecified or a trap, as you say: https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+no... But. This part says that reading an indeterminate value is, in fact, undefined behavior (line 11 in the table): https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_11 https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+...
- tspiteri 7y agoThat says used, not read. And indeterminate, not unspecified. My point was on reading a value, not on acting on the value. I know it looks like nit-picking, and you should just not read uninitialized memory, but I don't think it's consistent with the standard to say that reading uninitialized memory is always UB.
- lmm 7y agoWhat kind of read would not constitute "using" a value? And per your previous post an object that was not initialised is indeterminate, not just unspecified. So yes, reading uninitialized memory is always UB.
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- madmax96 7y agoA read into a character type. From 6.2.6.1¶5: >Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. ... Such a representation is called a trap representation. A read from uninitialized memory is not always UB.
- lmm 7y agoWhat you quoted doesn't actually say anything about what happens when a trap representation is read into a character type. Such a read is still "using" the value at least in the everyday sense of the word, so in the absence of something explicitly to the contrary, as far as I can see the part of the standard that states that using an uninitialised value is UB stil applies. Per http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_451.htm , the current standard is unclear in some respects, but the latest committee view is that that under the current standard any library function (including memcpy) may exhibit undefined behaviour when called with uninitialized memory, even when the uninitialized memory is of character type or is propagated through values of character type.
- dooglius 7y agoThat's the way I think it _should_ work, but sadly does not. For instance, see https://godbolt.org/z/ent-xp https://godbolt.org/z/ent-xp
- tspiteri 7y agoYour code is int x; if(x == 0) foo(); if(x != 0) foo(); That is reading the uninitialized value twice. Since it is unspecified, it does not have to be consistent, so you could get the same behavior as non-zero for the first reading, and zero for the second reading. Changing your code to: int x; if(x == 0) foo(); else foo(); will give different output (same if you use !=).
- ncmncm 7y agoA good optimizing compiler will just elide the whole code block.
- tspiteri 7y agoOnly if there was UB, and the point is that there probably isn't. (I'm not really knowledgeable on the C standard, so I might have misinterpreted something.)
- ncmncm 7y agoMaking an "if" statement depend on the value of the uninitialized memory is an example of what is meant by using the value, and thus UB. In the compiler discovers UB, the Standard places no requirements of any kind on the program or compiler. It is free to launch missiles, or (more likely) assume this code cannot be reached, and omit it from the program, along with any code that reaches it unconditionally, and any check that would send control that way. Such elision is the basis for many important optimizations. Implementations are free to define things left undefined by Standards. For example, "#include <unistd.h>" is UB by the ISO Standard, but defined by Posix, which implementations also adhere to.
- 7y ago
- umanwizard 7y agoThanks, it seems you are right. Sorry that you got downvoted whereas my wrong statement got upvoted; such is the nature of HN.