EXE 如何静态依赖于 DLL?
通常,当尝试运行使用 DLL 的 EXE 时,如果缺少 DLL,您会收到标准 Windows 错误:
程序无法启动,因为 您的计算机中缺少 XXX.dll。 尝试重新安装程序来修复 这个问题。
这似乎是在调用任何代码之前内置到 EXE 中的...它是如何工作的,以及在 Visual Studio 中构建项目时如何设置它?
编辑:
在我的特定场景中,我实际上有一个 DLL,它对其他 DLL 具有“静态”依赖关系,因此如果这些不存在,注册我的 DLL 就会失败,这有点难以诊断。但我不想手动列出曾经使用过的 DLL 函数,因为有很多!
Often when trying to run an EXE which uses a DLL, if the DLL is missing you get a standard Windows error:
The program can't start because
XXX.dll is missing from your computer.
Try reinstalling the program to fix
this problem.
This seems to be built-in to the EXE before any of your code gets called... how does it work, and how does this get set up when building a project in Visual Studio?
edit:
In my specific scenario I actually have a DLL which has "static" dependencies on other DLLs so if those aren't present, registering my DLL fails which is a little hard to diagnose. But I'd rather not manually list ever DLL function used as there are lots!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当链接到 DLL 时,有两种方法可以实现此目的:隐式链接和显式链接。您遇到的是隐式链接失败。
隐式链接通过包含在使用 PE(可移植可执行文件)格式的可执行映像中的导入表进行操作。 PE 格式定义了导入表和导出表。导出表包含 DLL 导出的函数列表及其入口点。导入表包含对其他模块的隐式依赖关系。
当可执行文件启动时,加载程序会读取导入表,然后尝试加载所有引用的 DLL 以及这些 DLL 中的所有函数。如果找不到 DLL、无法正确加载 DLL 或者 DLL 不包含引用的函数,则此操作可能会失败。在您的情况下,它失败是因为加载程序在 DLL 搜索路径中找不到
XXX.dll
。链接器将生成导入表。在 C++ 中,这通常是通过该 DLL 的 .lib 文件完成的。
显式链接是指您的代码调用
LoadLibrary
和GetProcAddress
来加载 DLL 及其函数的位置。通常,当您想要编写可以在不同系统上运行的应用程序时,请使用此方法。例如,您可能希望使用仅在某些版本的操作系统上存在的某些功能,但在旧版本的操作系统上运行时会降级为某些其他行为。当引用链接到 DLL 时,不应使用术语静态。静态链接是指函数的实现包含在图像中而不是包含在外部库中。
有关该主题的 MSDN 文章 解释了这一切等等。
When you link to a DLL there are two ways to do this, implicit linking and explicit linking. What you are encountering is a failure of implicit linking.
Implicit linking operates through something called the import table contained in the executable image which uses the PE (Portable Executable) format. The PE format defines both import and export tables. The export table contains the list of functions exported by a DLL, and their entry points. The import table contains the implicit dependencies on other modules.
When an executable starts the loader reads the import table and then tries to load all the DLLs referenced and all the functions in those DLLs. This can fail if the DLL is not found, if the DLL fails to load properly, or if the DLL does not contain the referenced functions. In your case it is failing because the loader did not find
XXX.dll
in the DLL search path.The linker will generate the import table. In C++ this is typically done via the .lib file for that DLL.
Explicit linking is where your code calls
LoadLibrary
andGetProcAddress
to load a DLL and its functions. Typically this approach is used when you want to write an app that can run on different systems. For example you may wish to use certain functions that are only present on certain versions of the OS, but degrade to some other behaviour when run on an older version of the OS.The term static should not be used when referring to linking to DLLs. Static linking is when the implementation of a function is included in an image rather than contained in an external library.
The MSDN article on the topic explains all this and more.