Namespaces
Variants
Actions

Talk:cpp/string/byte/memcpy

From cppreference.com

I have some issues with the parts about non-trivially-copyable types. First of all, but maybe that's just me:

If the objects are not TriviallyCopyable (e.g. scalars, arrays, C-compatible structs)

it is not obvious to me from the phrasing if "scalars, arrays, .." are trivially copyable or not.

Then, I am rather sure that for certain objects, the invocation of memcpy itself has Undefined Behaviour. Not all C++ objects have memory layouts compatible with the C object model: C++ has noncontiguous objects. See my StackOverflow answer for an example. [intro.object]p5 says

An object of trivially copyable or standard-layout type shall occupy contiguous bytes of storage.

C specifies that objects occupy contiguous bytes in 6.2.6.1p2 I conclude that C++ objects whose types are neither standard-layout nor trivially copyable are not required to be compatible with the C object model. For C++ objects that are incompatible, I'd guess that the behaviour of memcpy is undefined.

Additionally, it is unclear to me if memcpy has defined behaviour for standard-layout types that are not trivially copyable. For example, can you change the type of an object via memcpy? - e.g. by copying the value of an object into a character array and from there into an object of a different type? This might have implications for aliasing optimizations; see also this discussion.

Until these issues have been resolved unambiguously, I'd suggest either to restrict the description of memcpy to trivially copyable types, or add a warning that the effects on standard-layout types which are not trivially copyable are under discussion + there is no specification for memcpying types which are neither standard-layout nor trivially copyable.

dyp --91.14.125.125 18:33, 28 April 2015 (PDT)

good point about non-contiguous memory layout! Let's just link to SO. --Cubbi (talk) 18:45, 28 April 2015 (PDT)
Wow, you're fast. It occurred to me that even trivially copyable is not sufficient to make memcpy well-behaved. [basic.types]p2 specifically excludes base class subobjects, and sure enough, memcpying an empty base class subobject has inconsistent behaviour. This of course includes my example using virtual inheritance, but I guess the general argument of noncontiguous objects still holds. dyp --84.171.80.135 06:51, 29 April 2015 (PDT)
I wrote this quip about trivially-copiable types on this page, so naturally I am interested in how wrong I was. I think when I put it in, I was looking at basic.types/2 and my reasoning was "what is not defined is undefined". I just overlooked the "other than a base-class subobject" bit. --Cubbi (talk) 07:03, 29 April 2015 (PDT)

Where strict aliasing prohibits examining the same memory as values of two different types, std::memcpy may be used to convert the values.

This is subject to N3751 (I'm not sure if there's a DR about it). But that might very well be too far into language-lawyer-land to be of any practical use. That is, even if we follow Dos Reis' interpretation that this is UB, if it's common practice, it might not be worth the trouble pointing out on cppreference that it's currently UB. There's also a related discussion on the UB reflector.

dyp --84.171.80.135 10:22, 29 April 2015 (PDT)

As someone who brought plenty of objects into being by memcpy'ng their representations from IPC/network, I home Richard Smith is right. Possible weasel wording: s/may be used/is often used --Cubbi (talk) 10:48, 29 April 2015 (PDT)

[edit]round 2

This topic is making another round on StackOverflow and more than one person seems to read our "not specified and may be undefined" as "unspecified behavior". --Cubbi (talk) 05:47, 18 March 2016 (PDT)

close