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