6

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

Bart
  • 1,633
  • 14
  • 21
  • 8
    I never use precompiled headers and don't have any issues. – Retired Ninja Aug 26 '12 at 21:05
  • 5
    Precompiled headers are not required to build a DLL or anything else. – Steve Wellens Aug 26 '12 at 21:06
  • 1
    I created many DLLs without precompiled header in MSVC. what make you think that pch is the cause of your error and what do you do in your DllMain and in constructor of your static and global objects? – BigBoss Aug 26 '12 at 21:07
  • I totally agree with all the comments above. instead you should be doing something wrong in the linker double check it. – Mahmoud Fayez Aug 26 '12 at 21:14
  • @BigBoss: `DllMain` just returns `TRUE`, and the DLL only contains one hello world style function. The function is `export "C"`, and the DLL contains no C++ classes. Also I don't have any global variables. – Bart Aug 26 '12 at 21:14
  • @MahmoudFayez: I would be very surprised if something's wrong with the linker stuff. The DLL project was freshly generated by the VS wizard, and the only thing I changed was the precompiled header thingy. – Bart Aug 26 '12 at 21:18
  • Please edit the question and add the function declaration. – Mahmoud Fayez Aug 26 '12 at 21:21
  • The error code (0xc000000d: STATUS_BAD_INITIAL_STACK) say that have corrupted your stack, can you say what kind of DLL are you trying to create( MFC DLL, Win32, console, ... )? – BigBoss Aug 26 '12 at 21:36
  • @BigBoss: It's a console DLL project. Error 0xc000000d is defined as `STATUS_INVALID_PARAMETER` in `ntstatus.h`, where did you find the bad initial stack definition? – Bart Aug 26 '12 at 22:10
  • I have a large body of source code some of which uses pre-compiled headers for DLLs and some that do not. The 0x57 is STATUS_INVALID_PARAMETER according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx. I suspect that there is a function call parameter list problem that the pre-compiled headers allow the compiler to fix for you but without which the compiler is providing the wrong arguments. – Richard Chambers Aug 27 '12 at 00:45
  • @RichardChambers What do you mean by function parameter list problem? The problem occurs before any function from the DLL has been called, `LoadLibrary()` fails before a function can be called. – Bart Aug 27 '12 at 05:25
  • Sounds like the version of the CRT DLL you need isn't installed. Welcome to DLL Hell. As a temporary solution, maybe try linking statically (/MT or /MTd). – user541686 Aug 27 '12 at 22:20

3 Answers3

7

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

Community
  • 1
  • 1
ta.speot.is
  • 26,914
  • 8
  • 68
  • 96
  • Maybe I should have chosen another title, it seems more like a bug (and that's what I thought in the first place). See my last edit. – Bart Aug 27 '12 at 14:22
  • @Bart Tick "Empty project" and you'll get a stdafx.h-less DLL. – ta.speot.is Aug 27 '12 at 20:00
  • @Bart What are you trying to do? Create a DLL that can be dynamically loaded and calling a function in it from another application? I can try to give you a minimal walk through for that if it might help. Incremental linking shouldn't make a difference. – ta.speot.is Aug 27 '12 at 20:10
  • Even if you create an empty project (which indeed has PCH disabled) the problem persists. – Bart Aug 27 '12 at 21:03
4

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.

Bart
  • 1,633
  • 14
  • 21
  • Glad you figured it out and found how to reproduce it. I've made DLLs with and without PCH and I've never seen this. If I speculate, the only thing that comes to mind is your language/locale settings (I'm associating UTF-16 with i18n). Is your computer `en-US` (or otherwise English) or perhaps some other language? – ta.speot.is Sep 01 '12 at 11:08
  • I'm running en-us Windows. Never experienced any tool creating UTF-16 stuff before. – Bart Sep 03 '12 at 09:24
0

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.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Counterexample: Suppose you introduce a bug in a corresponding .cpp file but the .hpp is untouched. PCH will not help you there, whereas linking with the old object file will. – moshbear Aug 27 '12 at 09:32