Nothing can go wrong when the source and destination to memcpy() are identical, yet memcheck 3.2.3 still complains: ==3031== Source and destination overlap in memcpy(0x4077E00, 0x4077E00, 4) ==3031== at 0x4006A3A: memcpy (mc_replace_strmem.c:116) ==3031== by 0x1D952D: (within /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x1DA486: _XtGetResources (in /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x1C4F89: (within /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x1C582A: _XtCreateWidget (in /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x1F1992: (within /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x1F1AD4: XtVaCreateManagedWidget (in /usr/X11R6/lib/libXt.so.6.0) ==3031== by 0x8063DE2: (within /usr/bin/xterm) ==3031== by 0x544D7E: (below main) (in /lib/libc-2.3.6.so) This particular case was generated by "valgrind xterm" where xterm is from xterm-213-1.FC4, and libXt.so is from xorg-x11-libs-6.8.2-37.FC4.49.2.1 , and "valgrind --version" reports valgrind-3.2.3 .
John Reiser wrote: > Nothing can go wrong when the source and destination to memcpy() are identical, > Not true. memcpy is undefined when source and dest overlap. For example, a powerpc implementation might use the dcbz on the destination, which has the effect of zeroing a cache line, potentially before it has been read as a source. J
The Standard does say that any overlap in memcpy() results in Undefined. Therefore, the original complaint may be dismissed as "Not a bug." However, I could amend the complaint with the qualification "on my machine" [not a PowerpC] or "for lengths much less than a cacheline" [in this case, for length 4.] Then we could discuss particular aspects of portability. Another applicable Standard says that (0 + x) is Undefined whenever x is Uninitialized, yet memcheck complains only if memcheck believes that the result affects visible state. To memcheck, some violations of relevant Standard are ignored, and others are not. Trying to understand (or even enumerate) the differences confuses to both new and expert users. The calculus of "What are the implications of a complaint [or no complaint] by memcheck?" becomes muddied by many cases.
You could say a lot about specific portability issues - for example, a certain uninitialized variable on the stack just happens to be OK all of the time on my machine - but that isn't useful in the general case. Amongst its many other uses, Valgrind is helping you spot things that may be problems on some machines or in some circumstances even if they work just fine for you on your particular machine.
(In reply to Robert Walsh from comment #3) > You could say a lot about specific portability issues - for example, a > certain uninitialized variable on the stack just happens to be OK all of the > time on my machine - but that isn't useful in the general case. Amongst its > many other uses, Valgrind is helping you spot things that may be problems on > some machines or in some circumstances even if they work just fine for you > on your particular machine. I agree. But if things work fine, then suppression may be useful. What do you think of adding a way to write a specific suppression that handles exactly that src and dst in a memcpy are identical? Currently it's only possible to write a generic suppression that matches every overlap, or really write suppressions specific for a given program.
Sorry for posting again but I forgot to point out that this is a real problem in cases where compilers generate calls to memcpy() even if there's no explicit memcpy() call in the source, e.g., struct assignments. This happens for both GCC and Clang, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32667 https://bugs.llvm.org/show_bug.cgi?id=11763 Of course it could be "fixed" there but it seems that at least Clang will move in the opposite direction and simply assume from libc that memcpy(x,x,n) is fine. So I think a suppression in Valgrind or at least a way to write one will be very useful and pragmatic.