> 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.
How about undefined behaviour such as the following: if (backwards) { fprintf(stderr, " ----------\n"); fprintf(stderr, " / \\\n"); fprintf(stderr, " / REST \\\n"); fprintf(stderr, " / IN \\\n"); fprintf(stderr, " / PEACE \\\n"); fprintf(stderr, " / \\\n"); fprintf(stderr, " | Steffen |\n"); fprintf(stderr, " | 0 Au |\n"); fprintf(stderr, " | killed by a |\n"); fprintf(stderr, " | backward |\n"); fprintf(stderr, " | memcpy |\n"); fprintf(stderr, " | 2017 |\n"); fprintf(stderr, " *| * * * | *\n"); fprintf(stderr, " _________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n"); reboot(RB_NOSYNC); abort(); }