-
Notifications
You must be signed in to change notification settings - Fork 262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
64-bit Visual Studio /MT labels memmove as "memcpy", resulting in failure as replace_memcpy (correctly) does not handle overlap #1868
Comments
Enabling our app_suite for 64-bit, I do see the memmove test failing. However, it looks like the issue is that the compiler is calling memcpy instead of memmove when the source code asks for memmove. |
No such issue happens if exactly the same executable is run without Dr.Memory. Not a compiler issue for sure. |
There is no problem with 64-bit replace_memmove on Linux or with 64-bit mingw on Windows, or with 32-bit anywhere. This is a problem specific to 64-bit Visual Studio. Building this app:
With 32-bit Visual Studio 2010 or 2013, it always calls memmove, even with /GF and other flags. But building it with 64-bit VS 2010, 2012, or 2013, with simple flags such as "cl /Zi /EHsc /MT", and it calls what is labeled as memcpy instead of memmove. This is a static routine included in the executable, and it appears to actually be handling overlap, but it is misleadingly labeled in the debug info as "memcpy". Note that the dumpbin output can be misleading, as with VS 2010 it appears to call memmove:
Yet windbg shows it as memcpy:
In fact there is no memmove:
Seeing a routine named "memcpy", Dr. Memory naturally replaces it with "replace_memcpy", leading to failure:
Using /MD, the compiler calls out to a shared library, where it has to get the names right, and everything works:
I would call this a compiler bug, though one that has no correctness consequences for running natively. It is quite annoying, as the only simple fix is to always use replace_memmove on 64-bit Windows for anything called "memcpy", which will be a performance hit. Note that MacOS and Linux libc implementations have run into similar things in the past, where applications relied on undefined behavior by assuming memcpy handled overlap, and I believe that MacOS libc aliases memcpy to memmove. The difference, though, is that they have both memcpy and memmove labeled properly, they just have both pointing at the same address. We'll handle this today b/c we process memmove after memcpy and will replace our memcpy replacement with our memmove replacement. |
One workaround is to build your app /MD. |
There are native consequences: an app calling a memcpy that handles overlap incurs unnecessary performance overhead. |
You are probably right, but I'm using Intel C++ Compiler 14 which means this bug is not limited to VS. |
Please provide the corresponding info for Intel C++ Compiler: is it the same underlying behavior -- i.e., naming the overlap version "memcpy" while not providing anything called "memmove", and only doing this for a static libc? Is this behavior limited to 64-bit compilation? |
Yes, this issue is limited to 64-bit compilation and static libc. Since Intel C++ Compiler is configured to use VS libraries (or Microsoft Platform SDK), the problem may be in this 64-bit library, not in the compilers. |
Visual Studio is confirmed as fixed. I filed https://connect.microsoft.com/VisualStudio/feedback/details/2506331 about the Visual Studio behavior, though it's a minor issue: we'll see what they say. |
I think Linus Torvalds was in favour of aliasing memcpy to memmove: https://bugzilla.redhat.com/show_bug.cgi?id=638477#c101 https://lwn.net/Articles/414467/ It sounds as though Microsoft may have done something similar, but a bit mixed up. There may be virtually no overhead from combining memcpy and memmove into a single function. There is certainly plenty of confusion if they call the combined function "memcpy". |
As mentioned above, MacOS libc already aliases memcpy to memmove, and for Linux it's sthg like memcpy@GLIBC_2.2.5 is aliased to memmove, but with the proper inclusion of both names these all work out fine. |
The issue happens in the DrMemory 1.10.0-2 64-bit on Windows 7 Pro. Due to this issue most code simply crashes.
The problem is that the original C memmove was designed to cope with overlapping memory regions. But the replacement memmove does not seem to work the same way.
The text was updated successfully, but these errors were encountered: