Protecting the world

from criminally bad code

memcpy

Synopsis

#include <string.h>

void* memcpy(void* restrict s1, const void* restrict s2, size_t n);

Description

memcpy copies a block of raw memory from one location to another.

Pitfalls

Overlapping source and destination buffers

The behaviour of memcpy is undefined if the source and destination buffers overlap[1]. Use memmove instead where there is a risk of this happening.

Maintaining alignment

Data types such as integers and floating point numbers are often subject to an alignment constraint that limits where they can be placed in memory. For example, 4-byte integers must often be placed at an address that is a multiple of 4 bytes. Normally the compiler would ensure that alignment constraints are respected, but using memcpy it is possible to copy an object to a misaligned address.

Doing so is not intrinsically harmful, and in some instances may be useful, but you must not attempt to use the data directly from its new location. Even creating a pointer or reference to the data is unsafe if it does not have the appropriate alignment for the referenced type. However the data can be safely used if you first copy it back to a suitably aligned address.

For example, the following would safely copy x to y regardless of the alignment constraint for an int:

int x=42;
int y=0;
char d[2*sizeof(int)];
memcpy(d+1,&x,sizeof(int));
memcpy(&y,d+1,sizeof(int));

whereas this would be unsafe:

int z=*(int*)(d+1);

as would:

int* p=(int*)(d+1);

(Note that a block of memory allocated by malloc is guaranteed to be sufficiently well aligned to be used for storing any supported data type[2].)

Copying non-POD types (in C++)

Some types of class, structure and union in C++ cannot be safely copied using memcpy. Those that can are known as POD types (‘Plain Old Data’). A useful rule of thumb is that types which would be valid in C are always POD types, whereas those which make use of the object orientated capabilities of C++ are often not.

An example of a type that cannot be safely copied using memcpy is std::string. This is typically implemented using a reference-counted shared pointer, in which case it will have a copy constructor that causes the counter to be incremented. If a copy were made using memcpy then the copy constructor would not be called and the counter would be left with a value one lower than it should be. This would be likely to result in premature deallocation of the memory block that contains the character data.

Alternatives

Using memmove

memmove provides the same functionality as memcpy, except that it is able to handle source and destination buffers that overlap[3]. There is usually a performance penalty for choosing memmove, which is why the standard library provides both functions.

Portability

  •  C90
  •  C99
  •  C++98
  •  C++11

In C++, use of the header <string.h> is deprecated in favour of <cstring>.

Notes

  • [1] C99 §7.21.2.1 ¶2
  • [2] C99 §7.20.3 ¶1
  • [3] Implied by C99 §7.21.2.2 ¶2

Further reading

  • The memcpy function, Programming languages — C, ISO/IEC 9899:1999, §7.21.2.1, p324
  • memcpy, The Open Group Base Specifications, Issue 7, The Open Group, 2008
  • memcpy(3), Linux Programmer’s Manual, The Linux man-pages project
  • Copying and Concatenation, The GNU C Library Reference Manual, The GNU Project