4 ms·
Yet memcpy(0, 0, 0) is still undefined behavior? For shame.
by quotemstr 10y ago
Yet memcpy(0, 0, 0) is still undefined behavior? For shame.
- vardump 10y agoPlease read the edit below. This case has a very subtly trap. ------ Old comment: Makes sense it's undefined behavior, because address 0 is involved. Although I'd guess compiler implementations might just drop whole statement, because length is 0. Zero length memory copy is a no-op. Just like static zero iteration loop. They become zero instructions. (Except of course initialization that affects something outside loop scope.) Edit: Changed my mind after learning about the tricky UB pathway: If compiler can statically prove memcpy length argument to be zero, it can ALSO prove both argument pointers to be not NULL! Ouch!
- Rarebox 10y agomemcpy(0x1, 0x1, 0) is a well-defined no-op even when you don't have 0x1 in your address space. Why handle 0x0 differently?
- vardump 10y agoWell, just before I just saw a "read" and a "write" to address 0. Not as mechanism that can cause serious bugs, when the compiler can statically prove length argument to be 0 and you can have NULL arguments as input. Calls to memcpy with zero length are definitely not uncommon. Macros are an obvious way, but it's worse. All you need is a data flow where compiler can statically prove that all paths lead to zero length argument. I have to agree it's very scary that memcpy(NULL, NULL, 0) is undefined.
- plorkyeran 10y agoPassing a non-null pointer that points outside your address space is made UB by the exact same sentence as the one that makes passing null UB.
- quotemstr 10y ago> memcpy(0x1, 0x1, 0) is a well-defined no-op Sure about that? It really should be a no-op. The C and C++ standards are seriously broken in this respect, and compiler authors take advantage of this brokenness to get away with miscompiling programs that, to anyone with common sense, are fine.
- quotemstr 10y agoIt makes absolutely no sense for this behavior to be undefined, and letting it be undefined behavior causes real problems. See https://www.imperialviolet.org/2016/06/26/nonnull.html https://www.imperialviolet.org/2016/06/26/nonnull.html The C and C++ standards must be changed to explicitly state that memory operations on zero bytes do nothing regardless of whether the inputs are valid pointers.
- vardump 10y agoOuch. Didn't think about that compilers can then assume passed pointers aren't NULL. And proceed to optimize your NULL checks away, because that memcpy would have been undefined behavior. It seems so obvious after reading that. Should always ask oneself "what can the compiler prove as a consequence of this undefined behavior?". So, you're right, memcpy(NULL, NULL, 0) should be defined as a no-op.
- quotemstr 10y agoSome of us been trying to highlight for a long time now how compilers are taking unjustifiable liberties with undefined behavior
- vardump 10y agoWell, undefined behavior is generally a good thing. It enables a lot of very reasonable optimizations. Zero-length memcpy pathway to UB is not obvious, because whether the whole thing is UB depends on whether compiler can statically prove the length to be zero. Ugh.
- quotemstr 10y agoI think the statically-prove-length-is-zero thing is a distraction. What do you think of memcpy(ptr1, ptr2, 1)? The compiler should be able to assume (legitimately, this time) that ptr1 and ptr2 are non-null. The problem isn't a special case for zero length: the problem is the lack of a special case for zero length.
- halayli 10y agomemcpy behavior is not part of C++ standard. The C++ standard is only concerned with formally defining the ability to use it and the header name to include.
- vardump 10y agoStrictly interpreting true, but grandparent's point is very valid. It's used everywhere in real life C++ code. quotemstr got a very good point and I'm grateful for the heads up.
- halayli 10y agobut memcpy outside the C++ scope is what I meant. The C++ committee cannot do much about memcpy but they can introduce a new memcpy with a different name that has better ub support.
- Kristine1975 10y agoThe C++ committee can and does change how functions of the C standard library work in C++, see Appendix C of the C++ Standard (granted, most of those changes simply specify how the library functions interact with C++ features). C++ is not 100% compatible with C.
- smitherfield 10y agoBut the C++ standard could, without any changes to C, be amended to formally define which assumptions the compiler may or may not make about the C API in certain edge cases, such as memcpy(0,0,0).
- halayli 10y agomemcpy is outside the territory of C++. it doesn't fall under the language specification. it's as simple as that. If they go this route what stops them from defining assumptions to system calls?