Reputation: 737
In C and C++, is it undefined behavior to memcpy
into a const
variable when the number of bytes to be copied is zero?
int x = 0;
const int foo = 0;
memcpy( (void *)&foo, &x, 0 );
This question is not purely theoretical. I have a scenario in which memcpy
is called and if the destination pointer points to const
memory, then the size argument is guaranteed to be zero. So I'm wondering whether I need to handle it as a special case.
Upvotes: 36
Views: 2804
Reputation: 81217
It's clear that on the vast majority of platforms, an implementation which would process memcpy(anything, anything, 0) as a no-op, regardless of the validity of the source and destination pointers, would be in every way, in essentially every non-contrived scenario, as good or better than one that does anything else.
The way the Standard is written, however, could be interpreted as specifying that compilers are allowed to treat as UB any situation where the destination address is not associated with writable storage.
If one is using an implementation that seeks to process corner cases applying the philosophy documented in the Rationale document published by the authors of the Standard, without regard for whether the Standard unambiguously mandates such behavior, all memcpy
and memmove
operations where the size is zero will be reliably processed as no-ops. If the size will often be zero, there may be performance advantages to skipping a memcpy
or memmove
call in the zero-size case, but such a check would never be required for correctness.
If, however, one wishes to ensure reliable compatibility with compiler configurations that aggressively assumes that code will never receive inputs that trigger corner cases that aren't 100% unambiguously mandated by the Standard, and is designed to generate nonsensical code if such inputs are received, then it will be necessary to add a size==0 check in any case where a zero size might be accompanied by anything other than a pointer to writable storage, recognizing that such a check may negatively affect performance in situations where the size is very seldom zero.
Upvotes: -2
Reputation: 58473
The older question Is it guaranteed to be safe to perform memcpy(0,0,0)? points out 7.1.4p1:
Each of the following statements applies unless explicitly stated otherwise in the detailed descriptions that follow: If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined.
The prototype for memcpy
is
void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
where the first parameter is not const
-qualified, and &foo
points to non-modifiable storage. So this code is UB unless the description of memcpy
explicitly states otherwise, which it does not. It merely says:
The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1.
This implies that memcpy
with a count of 0
does not copy any characters (which is also confirmed by 7.24.1p2 "copies zero characters", thanks Lundin), but it does not exempt you from the requirement to pass valid arguments.
Upvotes: 39