Question

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...

Was it helpful?

Solution 2

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.

  • As described building a DLL with PCH disabled results in a manifest resource containing only an UTF-16 LE BOM.
  • If a DLL is built with PCH enabled, the manifest resource contains a UTF-8 BOM followed by valid XML.
  • If a DLL is built with PCH disabled AND incremental linking disabled, the manifest resource contains only XML and no BOM at all.

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.

OTHER TIPS

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.

Wizard

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).

With "precompiled" headers, you are effectively using code that was compiled earlier. If you introduced a bug later, "precompiling" will not compile the bug but use the older bugfree code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top