5

总结:今天我发现当一个 DLL 在没有预编译头的情况下构建时,当你尝试使用它时会出现一个奇怪的错误。

禁用预编译头文件时,构建 DLL 可以正常工作。但是,一旦附加了 DLL(编译时或运行时),就会导致错误“无效参数”。两种情况的实际错误代码不同。附加编译时弹出一个对话框,错误代码为 0xc000000d,调用LoadLibrary()它时返回一个NULL指针并GetLastError()返回 0x57。

编辑:

我发现禁用增量链接后问题就消失了。在运行附加到 DLL 编译时的客户端时,不知何故我错过了 Visual Studio 显示的以下错误:

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

根据要求,函数声明:

#ifdef __cplusplus
extern "C" {
#endif

MYTEST_API int MyTestFoo(int a);

#ifdef __cplusplus
}
#endif

这是一个值得注意的一件事:当您使用向导(新项目 - > Visual C ++-> Win32-> Win32 Project)创建新的DLL时,向导会强制您在选择DLL作为应用程序类型时使用预编译标头。请参阅 ta.speot.is 的答案。

我彻底改变了这个问题,因为它看起来就像我认为它以某种方式记录了 DLL 项目需要 PCH。事实并非如此,它可能是一种奇怪的错误(希望不是)或者我可能正在做一些非常愚蠢的事情......

4

3 回答 3

6

为什么在构建 DLL 时需要预编译头文件?

他们不是。

总结:今天我发现如果不使用预编译的头文件构建它,就不可能制作一个(正常运行的)DLL。有谁知道这是什么原因?

发现这一点的原因是您误读了某些内容。

您可以制作没有预编译头文件的二进制文件就好了。

这是一个值得注意的一件事:当您使用向导(新项目 - > Visual C ++-> Win32-> Win32 Project)创建新的DLL时,向导会强制您在选择DLL作为应用程序类型时使用预编译标头。

也许在 Visual C++ 6 中,但我对 Visual Studio 的经验表明并非如此。如果您使用向导创建一个空项目,则不会获得预编译的头文件。

向导

除此之外,我在 Google 上查看了“对于它的清单,ntstatus 0xc000000d”,最终我在这里结束了。最后一个答案表明您的 CRT 版本不匹配,如果您让 Visual Studio 为您创建项目并坚持默认设置,这将很难做到。

检查您是否在“主机”应用程序和库中链接到相同版本的 CRT 可能会有所帮助(例如,两者都是多线程调试)。

我能想到的唯一另一件事是您正在TestDll.dll进入Debug没有随附TestDll.dll.manifest文件的文件夹(如果有的话)。

于 2012-08-27T08:40:13.760 回答
4

我发现 DLL 有一个嵌入式清单资源,其中只包含一个 little-endian UTF-16 字节顺序标记。Windows DLL 加载程序在尝试加载此类 DLL 时崩溃并出现上述错误。

我确信这只是一个奇怪的错误:如果我使用 Visual Studio 或 MSBuild 构建 DLL,它会生成一个带有虚假清单资源的 DLL。如果我在命令行上手动执行 MSBuild 报告的命令,则 DLL 包含具有 UTF-8 BOM 的有效清单资源。

  • 如前所述,在禁用 PCH 的情况下构建 DLL 会导致清单资源仅包含 UTF-16 LE BOM。
  • 如果在启用 PCH 的情况下构建 DLL,则清单资源包含一个 UTF-8 BOM,后跟有效的 XML。
  • 如果在禁用 PCH 和禁用增量链接的情况下构建 DLL,则清单资源仅包含 XML,根本不包含 BOM。

另一种选择是在构建完成后使用资源编辑器删除有问题的清单资源,这样错误也会消失。

这是非常可重现的,使用向导或者如果您创建一个空项目并自己做所有事情。

于 2012-08-28T12:15:22.280 回答
0

使用“预编译”头文件,您可以有效地使用之前编译的代码。如果您稍后引入了错误,“预编译”将不会编译错误,而是使用较旧的无错误代码。

于 2012-08-27T08:38:37.130 回答