Protecting the world

from criminally bad code

memmove

Synopsis

#include <string.h>

void* memmove(void* s1, const void* s2, size_t n);

Description

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

Pitfalls

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 memmove 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)];
memmove(d+1,&x,sizeof(int));
memmove(&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[1].)

Copying non-POD types (in C++)

Some types of class, structure and union in C++ cannot be safely copied using memmove. 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 memmove 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 memmove 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 memcpy

memcpy provides the same functionality as memmove, except that it is not able to handle source and destination buffers that overlap[2]. 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.20.3 ¶1
  • [2] C99 §7.21.2.1 ¶2

Further reading

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