In summary: Today I discovered that when a DLL is built without precompiled headers, a strange error shows when you try to use it.
Building the DLL goes fine when precompiled headers are disabled. However as soon as the DLL is attached (either compile-time or run-time) it results in the error "Invalid parameter". The actual error codes are different for both cases. When attaching compile-time a dialog pops up with error code 0xc000000d, when calling LoadLibrary()
it returns a NULL
pointer and GetLastError()
returns 0x57.
EDITs:
I discovered that the problem goes away when incremental linking is disabled. Somehow I missed the following error showed by Visual Studio when running a client that attaches to the DLL compile-time:
'TestClient.exe': Loaded 'D:\Projects\PchDllTest2\Debug\TestClient.exe', Symbols loaded.
'TestClient.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll', Cannot find or open the PDB file
'TestClient.exe': Loaded 'C:\WINDOWS\system32\kernel32.dll', Cannot find or open the PDB file
'TestClient.exe': Loaded 'D:\Projects\PchDllTest2\Debug\TestDll.dll', Symbols loaded.
SXS: RtlCreateActivationContext() failed 0xc000000d
LDR: LdrpWalkImportDescriptor() failed to probe D:\Projects\PchDllTest2\Debug\TestDll.dll for its manifest, ntstatus 0xc000000d
Debugger:: An unhandled non-continuable exception was thrown during process load
The program '[5292] TestClient.exe: Native' has exited with code -1073741811 (0xc000000d).
As requested, the function declaration:
#ifdef __cplusplus
extern "C" {
#endif
MYTEST_API int MyTestFoo(int a);
#ifdef __cplusplus
}
#endif
There's one thing that is remarkable about this: When you create a new DLL using a wizard (New project -> Visual C++ -> Win32 -> Win32 Project), the wizard forces you to use precompiled headers when selecting DLL as application type. See answer from ta.speot.is.
I drastically changed the question, as it looked first like I thought that it was somehow documented that PCH is required for DLL projects. This is not the case, it's probably a weird kind of bug (let's hope it's not) or probably I'm doing something very stupid...
Usage of precompiled headers may significantly reduce compilation time, especially when applied to large header files, header files that include many other header files, or header files that are included in many translation units.
Precompiled headers (PCH) are a performance feature supported by some compilers to compile a stable body of code, and store the compiled state of the code in a binary file. During subsequent compilations, the compiler will load the stored state, and continue compiling the specified file.
Why are precompiled headers required when building a DLL?
They're not.
In summary: Today I discovered that it's not possible to make a (functioning) DLL without building it with precompiled headers. Does anyone know what the reason is for this?
The reason for discovering this is that you misread something.
You can make binaries without precompiled headers just fine.
There's one thing that is remarkable about this: When you create a new DLL using a wizard (New project -> Visual C++ -> Win32 -> Win32 Project), the wizard forces you to use precompiled headers when selecting DLL as application type.
Perhaps in Visual C++ 6, but my experience with Visual Studio suggests otherwise. If you make an empty project with the wizard you do not get a precompiled header.
All that aside, I had a look on Google for "for its manifest, ntstatus 0xc000000d" and ultimately I wound up here. The last answer suggests that your CRT versions are mismatched, which would be very hard to do if you're letting Visual Studio create the projects for you and sticking with the defaults.
It might pay to check that you are linking to the same version of the CRT in your "host" application and library (e.g. both are multi-threaded debug).
The only other thing I can think of is that you're moving TestDll.dll
into the Debug
folder without its accompanying TestDll.dll.manifest
file (if it has one).
I found out that the DLL has an embedded manifest resource containing only a little-endian UTF-16 byte order mark. The windows DLL loader crashes with the described error when it tries to load such a DLL.
I'm convinced that this just is a weird bug: If I build the DLL using Visual Studio or MSBuild, it results in an DLL with the bogus manifest resource. If I execute the commands reported by MSBuild manually on the command line, the DLL contains a valid manifest resource with a UTF-8 BOM.
Another option is to remove the faulty manifest resource using a resource editor after the build has been completed, than the error also disappears.
This is very reproducable, using wizard or if you create an empty project and do everything yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With