Re: memcpy(3) && memmove(3)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Matthias,

This is not a GCC problem so we should have not discuss this in gcc-help.
But I'll still show my answer.

On 2017-05-05 09:00 +0200, Matthias Apitz wrote:

> We have a huge client/server application, mostly written in C. We moved
> now with it for the first time to 64-bit Linux (SuSE SLES 12 x86_64) and
> compiled with gcc 4.9.2, but with -m32 (because we have to support also
> 32-bit customers). The historical (20++ years) grown code was full of
> memcpy(3) calls, sometimes for overlapping memory, which is prohibited
> by the man page of memcpy(3), of course, and we got what we deserve:
> corrupted memory in destination of the copy. We nailed it down,
> substituted memcpy(3) by memmove(3) and all is fine.
> 
> What me motivates to this posting is:
> 
> Why the (wrong) usage of memcpy(3) did not showed up on SLES 11 and/or
> 32bit?

In memcpy(3): (my man-pages are version 4.04 from kernel.org)

 Under the previous implementation, the order in which the bytes were
 copied had fortuitously hidden the bug, which was revealed when the
 copying order was reversed.

> What is the exact problem with memcpy(3) prohibiting the overlapping
> memory,?

Also in memcpy(3):

 Most notably, in glibc 2.13 a performance optimization of memcpy() on
 some platforms (including x86-64) included changing the order in which
 bytes were copied from src to dest.

> And, last but not least: Why we have memcpy(3) at all, if memmove(3)
> gives the same result and is thread-safe too? For example, on my beloved
> FreeBSD memcpy(3) is implemented as bcopy(3), I checked the code for it,
> and allows even overlapping memory.

It's for performance.  Glibc memcpys are written in asm to maximize their
performance.  The developers can do anything conforming to the C89/C99
Standard to improve the performance.

We should always write programs conforming to standard while possible.
It's inproper to peek the internal implementation and say "it's safe".
For example, GCC has __builtin_memcpy and could do some optimization
beyond your imagination.  And FreeBSD may update their libc and break
your code.

If you have old source code relying on the old behaviour of memcpy, you
should change the code to use memmove.  If you are in hurry,
just sed 's/memcpy/memmove/' to make it work.  Then spend some time to
find non-overlapped cases and change them to use memcpy (which is faster
on many platforms).

If you have old binarys relying on old memcpy, don't worry. The man page
said:

 In glibc 2.14, a versioned symbol was added so that old binaries (i.e.,
 those linked against glibc versions earlier than 2.14) employed a
 memcpy() implementation that safely handles the overlapping buffers case
 (by providing an "older" memcpy() implementation that was aliased to
 memmove(3)).

Happy hacking.
-- 
Xi Ruoyao <ryxi@xxxxxxxxxxxxxxxxx>
School of Aerospace Science and Technology, Xidian University




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux