更改Windows DLL加载顺序?(加载订单,而不是搜索订单)

Mar*_* Ba 14 c++ windows dll loader

说我有一个可执行文件: app.exe

我在这个可执行文件中使用了2个不同的第三方DLL:foo.dll bar.dll应用程序必须隐式链接到这些DLL,即我无法用::LoadLibrary它们加载它们.

(注意:这不是我不能调用LoadLibrary,但这些DLL需要静态链接(C++ DLL __declspec(dllexport)),所以我调用LoadLibrary没有任何意义,因为可删除的加载器已经调用它.)

这两个DLL 彼此没有任何依赖关系,也就是说,就我所知,它们的加载顺序是不确定的(并且应该是无关紧要的).(两者的依赖性基本上只在标准的Windows dll(kernel32,msvcrt等)上

我现在有一个问题,我希望控制这些DLL的加载顺序,我希望foo.dll 总是DLL_PROCESS_ATTACH在bar.dll之前加载().

是否有可能告诉Windows DLL Loader在另一个之前加载一个DLL?

编辑:要检查可执行文件的DLL加载顺序,可以使用该DUMPBIN.exe实用程序:(只需启动Visual Studio命令提示符)

编辑:根据此答案/此博客条目,NT Loader 按顺序执行导入部分.(这将导致独立的 DLL按照它们在导入部分中出现的顺序加载.)

C:\path\to\program> dumpbin /IMPORTS app.exe | grep -i \.dll
  MSVCR80D.dll
  KERNEL32.dll
  OLEAUT32.dll
  MSVCP80D.dll
  foo.dll
  bar.DLL
Run Code Online (Sandbox Code Playgroud)

此输出表示将首先加载MSVCR80D.dll(及其依赖项[a]),最后将加载bar.DLL.卸载将以相反的顺序发生.

还没有发现的是如何影响这个加载顺序 ......


(笔记)

[a]:这当然意味着首先会加载kernel32.dll,因为msvcr80d.dll将依赖于kernel32.dll.


按一些要求,我加入一个理由是:(但,我仍然有兴趣在此一般.我知道如何解决该问题的MFC. )

它的调试版本中的Microsoft MFC DLL内置了内存泄漏检测.(据我所知,它与_CrtSetDbgFlag和相关工具使用的机制相同.)

MFC调试DLL将在卸载时转储所有未使用的内存.现在,如果您的进程中有第二个DLL,它独立于MFC,并且第二个DLL在DLL_PROCESS_DETACH上释放内存,则MFC报告机制将报告错误的内存泄漏,如果MFC DLL在另一个dll之前卸载.

如果可以确保首先加载调试MFC DLL /卸载所有独立DLL的最后一个,那么所有其他DLL本身已经清理完并且MFC不会报告错误泄漏.

Mac*_*cke 6

这里有一个想法:如何在 的链接器选项中将它们标记为“延迟加载的 dll” app.exe

延迟加载将允许您“静态”链接(即不使用 LoadLibrary() 等),但不会加载 DLL 并在实际需要时进行链接。

如果这是一个选项,那么(假设您可以等待这么长时间,即在 main() 之前不要访问 foo/bar dll 函数),您可以在 main() 中访问一个函数(只需获取函数 ptr 或其他东西)首先foo.dll,哪个会加载它并绑定所有“静态”链接的函数?

(也许 LoadLibrary() 会在需要时触发相同的链接过程。不确定。不过,它在您的代码中看起来会更干净。)

  • @STATUS_ACCESS_DENIED:我假设OP希望避免`LoadLibrary()`,因为使用`GetProcAddress()`来检索每个函数对于大多数应用程序来说非常麻烦,所以人们更喜欢导入库。仅使用 LoadLibrary 加载延迟导入的 dll(而不是调用返回 42 的虚拟函数)应该没问题。 (2认同)

Mar*_* Ba 6

我还没有发现的是如何影响这个加载顺序......

我不知道为什么我没有尝试过这个,但似乎结果模块的导入部分顺序确实取决于lib文件提供给链接器的顺序.

Configuration Properties -> Linker -> Additional Dependencies ...
Run Code Online (Sandbox Code Playgroud)

首先列出的lib文件也是导入部分的第一个,这意味着加载器将按顺序导入这些文件(模数依赖项).

因此,要回答这一部分:只需以正确的顺序向链接器提供lib文件.

注意:我在VS2005上尝试了它,它似乎工作.我不知道这是在某处记录还是在较新版本的VC++中有所改变.


更新:当它工作时,今天我遇到了加载顺序不受lib文件的链接器命令行顺序影响的情况.(仍然)不知道为什么.(仍然是VS2005)

然而,我设法通过将有问题的DLL添加到延迟加载的DLL列表(如Macke的答案)来使其工作.