Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing memcpy conformant with strict aliasing

The general answer when asking "how does one implement memcpy function conformant with strict aliasing rules" is something along the lines of

void *memcpy(void *dest, const void *src, size_t n)
{
    for (size_t i = 0; i < n; i++)
        ((char*)dest)[i] = ((const char*)src)[i];
    return dest;
}

However, if I understand correctly, compiler is free to reorder call to memcpy and access to the dest, because it can reorder writes to char* with reads from any other pointer type (strict aliasing rules prevent only reordering of reads from char* with writes to any other pointer type).

Is this correct and if yes, are there any ways to correctly implement memcpy, or should we just rely on builtin memcpy?

Please note, that this question concerns not only memcpy but any deserialization/decoding function.

like image 426
Oleg Andreev Avatar asked Jul 31 '14 13:07

Oleg Andreev


People also ask

How do you get around strict aliasing?

The answer typically is to type pun, often the methods used violate strict aliasing rules. Sometimes we want to circumvent the type system and interpret an object as a different type. This is called type punning, to reinterpret a segment of memory as another type.

What is the strict aliasing rule and why do we care?

GCC compiler makes an assumption that pointers of different types will never point to the same memory location i.e., alias of each other. Strict aliasing rule helps the compiler to optimize the code.

What is strict C++?

"Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias each other.)"


1 Answers

Since both (char*)dest and (char const*)src point to char, the compiler must assume that they might alias. Plus, there is a rule that says that a pointer to a character type can alias anything.

All of which is irrelevant for memcpy, since the actual signature is:

void* memcpy( void* restrict dest, void* restrict src, size_t n );

which tells the compiler that there cannot be aliasing, because the user guarantees it. You cannot use memcpy to copy overlapping areas without incurring undefined behavior.

At any rate, there's no problem with the given implementation.

like image 76
James Kanze Avatar answered Oct 24 '22 13:10

James Kanze