On Tue, 21 Feb 2017, Steffen Nurpmeso wrote:
...
> But mind you, it is true that i still think it is funny that this 
> happened on a BSD system, the origin of bcopy(3).  To me memcpy(3) never 
> has been anything but an optimization for cases where you know it is 
> save, so that the tests, the move to the end to start there etc., can be 
> avoided.  This was at least nine (9) cycles iirc on the above CPUs that 
> can be saved, and that almost sufficient to copy a small string! Ciao.

The catch is that that the standard *doesn't* say "memcpy() copies the 
buffer when they don't overlap or when the target is before the source". 
It says "memcpy() copies the buffer if they don't overlap; the behavior is 
not defined (i.e., *anything* can happen) if they overlap in any way".

Compilers now are saying "well, undefined behavior includes doing nothing 
or acting like the arguments were totally different; I will assume that 
this code path *cannot be reached* with arguments that have undefined 
behavior".  For example, it would be a totally legal optimization for a 
compiler to transform this:
        memcpy(p, p+1, n);
to
        if (n)
                p[0] = p[1];

The memcpy() behavior is only defined if there's no overlap, and overlap 
occurs if n>1, ergo the behavior is only defined if n is zero or one.  
Indeed, the compiler could then optimize the code *before* this memcpy() 
call on the assumption that _that_ code could only leave n set to zero or 
one!


If your code triggers the memcpy() log+abort, then the code only works 
elsewhere because the compiler isn't smart enough.  Yet.


Philip Guenther

Reply via email to