7 ms·
Yes, it's undefined. It involves a read of an uninitialized local variable. Except for the special case of unsigned char, any uninitialized read is undefined.
by msebor 6y ago
Yes, it's undefined. It involves a read of an uninitialized local variable. Except for the special case of unsigned char, any uninitialized read is undefined.
- emilfihlman 6y ago>Except for the special case of unsigned char, any uninitialized read is undefined. Could you expand on this?
- rseacord 6y agoUninitialized Reads https://queue.acm.org/detail.cfm?id=3041020 https://queue.acm.org/detail.cfm?id=3041020
- loeg 6y agoI'm guessing you were asking about this part rather than UB in general: > Except for the special case of unsigned char, The SO article makes the bizarre claim that because (1) an unsigned char, per the standard, cannot have any padding bits, it therefore cannot have a trap representation. And (2) if it cannot have a trap representation, the use of an uninitialized value isn't undefined. I'm willing to buy (1) but I don't remember (2) being required for UB. I think (2) is the step that is harder to follow intuitively. Admittedly, I have not read that part of the standard closely in some time.
- msebor 6y agoAn object of any type, initialized or not, can be read by an lvalue of unsigned char (or any character type). That lets functions like memcpy (either the standard one or a hand-rolled loop) copy arbitrary chunks of memory. There's some debate about the effects of reading an uninitialized local variable of unsigned char (like whether the same value must be read each time, or whether it's okay for each read to yield a different value). This special exemption doesn't extend to any other types, regardless of whether or not they have padding bits or trap representations that could cause the read to trap. Few types do, yet the behavior of uninitialized reads in existing implementations is demonstrably undefined (inconsistent or contradictory to invariants expressed in the code of a test case), so any subtleties one might derive from the text of the standard must be viewed in that light.
- MaxBarraclough 6y agoThanks for your answers. A related question: this article [0] appears to single out memcpy and memmove as being special regarding effective type. Is it accurate? It seems to be at odds with your suggestion that there's nothing stopping me writing my own memcpy provided I'm careful to use the right types. [0] https://en.cppreference.com/w/c/language/object#Effective_type https://en.cppreference.com/w/c/language/object#Effective_ty...
- AaronBallman 6y agoI think that may be inaccurate -- IIRC, in C, you can do type punning via a union but not memcpy, and in C++ you can do type punning via memcpy but not a union and this incompatibility drives me nuts because it makes inline functions in a header file shared between C and C++ really messy. (Moral of the story: don't pun types.)
- pascal_cuoq 6y agoThe C standard also allows to use memcpy to do type punning: If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one Simply memcpy into a variable (as opposed to dynamically allocated memory). https://port70.net/~nsz/c/c11/n1570.html#6.5p6 https://port70.net/~nsz/c/c11/n1570.html#6.5p6
- AaronBallman 6y agoI must be remembering incorrectly then, thank you!
- msebor 6y agomemcpy and memmove aren't special. The part that discusses the copying of allocated objects is 6.5, p6, quoted below: The effective type of an object for an access to its stored value is the declared type of the object, if any. If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is opied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.
- deleted 6y ago[deleted]