Debug run-time DLL issue
- 1 Issue found
- 2 Steps to reproduce
- 2.1 Install
- 2.2 Sample project
- 2.3 Steps
- 2.4 Expected behavior
- 2.5 Actual behavior
- 2.6 Sanity check
- 3 Investigation
- 4 Workaround
- 5 Tools
- 5.1 LDD
- 5.2 Dependencies
Issue found
Debug run-time dlls for arm64 are not installed properly by Windows 10 SDK.
C:\Windows\System32 path can’t be used for arm64 debug dll loading, even if dlls manual copied from Windows 10 SDK package directories.
Steps to reproduce
My system
Edition Windows 10 Enterprise
Experience Windows Feature Experience Pack 120.2212.3920.0
Install
Issue found
Visual Studio Community 2019 (Version 16.10.4)
Visual Studio Installer → Modify → Individual Components
C++ Universal Windows Platform support for v142 build tools (ARM64)
Windows 10 SDK (10.0.19041.0)
Re-tested and still reproduced with (at the time latest)
Visual Studio Community 2019 (Version 16.11.9)
Visual Studio Installer → Modify → Individual Components
C++ Universal Windows Platform support for v142 build tools (ARM64)
Windows 10 SDK (10.0.20348.0)
Sample project
hello_world.c
#include <stdio.h>
int main (void)
{
printf("Hello World");
}
Alternatively a new Visual Studio C/C++ project can be created.
Steps
Invoke vcvars for arm64
Build sample project with debug dll run-time libraries: “/MDd”
/MD, -MT, -LD (Use Run-Time Library)Try to run it, check it again in GUI to see error window.
/MDd Defines _DEBUG, _MT, and _DLL and causes the application to use the debug multithread-specific and DLL-specific version of the run-time library. It also causes the compiler to place the library name MSVCRTD.lib into the .obj file.
Commands in powershell
cmd /k '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsx86_arm64.bat" & powershell'
cd <project_dir>
cl /MDd .\hello_world.c
.\hello_world.exe
In Visual Studio the same flag can be set by (/MD, -MT, -LD (Use Run-Time Library))
Open the project's Property Pages dialog box. For details, see Set C++ compiler and build properties in Visual Studio.
Select the Configuration Properties > C/C++ > Code Generation property page.
Modify the Runtime Library property.
Expected behavior
Windows 10 SDK installs debug dlls into C:\Windows\System32 directory.
This directory is included in the PATH by default.
The hello_world sample application should be able to load the required and installed debug dlls, so it should print the hello world message, then exit successfully.
Just like as if it was built with non-debug dll loading requirements:
Actual behavior
The hello_world sample application fails to start as it can’t find the required debug dlls.
Sanity check
Are the debug dlls installed into System32? Yes
Is this directory included on the PATH? Yes
Investigation
Check dll header with dumpbin: ucrtbase*.dll
Release
Debug
Copy the debug dll into another directory:
Dumpbin the copy of the debug dll
Issues found here
The debug dll installed into System32 directory is for x86, while the release version is for ARM64.
In System32 directory the debug dll can’t be opened, but the same file is available on a different path!
Check debug dlls on other installed paths
ucrtbased.dll is packed by Windows 10 SDK to
Issues verified here
x86/ucrtbased.dll is the same file (based on file sizes) as the installed at C:\Windows\System32.
Copying the arm64/ucrtbased.dll to C:\Windows\System32 doesn’t fix the original problem as even dumpbin still can’t open that file on that path.
Again, on another path dumbpin can reach it and the header is for ARM64 as expected.
Workaround
Add any missing debug dll’s Windows SDK package directory to the path.
Example:
1. ucrtbased.dll
Path:
Command in cmd:
Command in PS:
2. vcruntime140.dll
Path:
Command in cmd:
Command in PS:
Tools
You can find missing dll using an msys prompt:
To see dependencies of a given executable, you can use:
LDD
ldd
(from cygwin/msys). It does not take into account arm64 arch, so it will only report first dll on your path. By using file
, you can verify every dependency.
Dependencies
Dependency Walker (depends.exe) Home Page used to be a good solution to see DLL deps using a GUI. It is now outdated, and does not handle ARM64 arch.
A replacement, Dependencies, is now written to modernize it. It works with ARM64 arch: GitHub - lucasg/Dependencies