Reputation: 12279
#include <cstdlib>
#include <cstring>
#include <iostream>
// C++03 only.
int main()
{
std::allocator<unsigned char> alloc;
double d = 8;
unsigned char* buf = alloc.allocate(sizeof(double));
std::memcpy(buf, &d, sizeof(double));
double extract;
std::memcpy(&extract, buf, sizeof(double));
std::cout << extract << '\n';
alloc.deallocate(buf, sizeof(double));
}
I've created storage for an array of bytes that I've never brought to life by initializing it, so its lifetime never started (and in C++03 that is basically impossible to do since the correct way of doing it is by placement new but for arrays it adds a memory offset that you don't know what is it)
But, I don't actually need to "directly read" the data that is in this storage, I do all of this copy-paste of objects by means of std::memcpy
calls.
My doubt is with the second std::memcpy
call. In terms of value access, is it considered that the std::memcpy
is reading the value of each buf
array element so this array must be alive?
NOTE: It has been suggested that, this question is a possible clone of Can memcpy be used for type punning?. That other question is about C, and this question is not about type punning either, although it's related (I wrote originally a wrong question title because I misundertood what type punning actually means). I'm asking here about the precise semantics of the reading-from object that is passed to memcpy
, whether that object must be alive or isn't actually required.
Upvotes: 1
Views: 516
Reputation: 141618
The std::allocator<unsigned char>::allocate
is specified as calling ::operator new
(C++03 lib.allocator.members/3). So this question is substantially similar to "constructing" a trivially-copyable object with memcpy , although without the attempt to alias a value afterwards.
If we replaced the call to memcpy
with a char assignment loop: unsigned char *p = (unsigned char *)&d; for (int i = 0; i < sizeof d; ++i) buf[i] = p[i];
then it is definitely undefined behaviour, since the assignment operator only has defined behaviour when the left hand side refers to an object that exists. See this answer for more detail.
However for the memcpy
version, the question is: is memcpy
the same as this char assignment loop, or something else?
The C++03 standard only defines memcpy
by deferring to ISO C90, which says:
The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1.
But it is unclear how to interpret this, since C has a different object model to C++. In C "object" means storage, whereas in C++ "object" and "storage" mean different things, and in the code in this question there is storage with no objects.
The answer by Shafik Yaghmour therefore describes the situation as "unspecified", although I think "not specified" or "unclear" would be better descriptions, since the term "unspecified" has a specific meaning in C++.
Footnote: Nothing substantial changed on this topic as of C++17. But in C++20 this will be well-defined, accepted proposal detail.
Upvotes: 2