更改Windows DLL加载顺序? (加载顺序,不是搜索顺序) [英] Changing Windows DLL load order? (load order, not search order)

查看:146
本文介绍了更改Windows DLL加载顺序? (加载顺序,不是搜索顺序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个可执行文件: 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?



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



编辑:根据这个答案 / 这个博客条目,NT Loader 顺序地导入部分(这将导致 indepen凹陷 DLL按照它们在导入部分显示的顺序加载)。

  C:\path\ to\program> dumpbin / IMPORTS app.exe | grep -i \.dll 
MSVCR80D.dll
KERNEL32.dll
OLEAUT32.dll
MSVCP80D.dll
foo.dll
bar.DLL

此输出意味着MSVCR80D.dll(及其依赖 [a] )将首先加载该bar.DLL将最后加载。卸载将以相反的顺序进行。



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






(Notes)



[a ]:这意味着,例如, kernel32.dll将被首先加载,因为msvcr80d.dll将取决于kernel32.dll。






根据一些请求,我为此添加了一个理由:(但,我仍然对这一般感兴趣。我知道如何解决MFC问题。



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



MFC调试DLL在卸载时将转储所有未被释放的内存。现在,如果你的进程中有一个第二个DLL,那就是独立于MFC,而这个第二个DLL释放DLL_PROCESS_DETACH上的内存,MFC的报告机制将报告错误的内存泄漏,如果MFC DLL在其他dll之前被卸载。 p>

如果可以确保调试MFC DLL在最后的所有独立DLL中被首先加载/卸载,那么所有其他DLL将在自己之后已经清理,MFC不会报告错误的泄漏。

解决方案


我还没有发现的是如何影响这个负载订单...


我没有任何线索,为什么我没有尝试过这个,但似乎导入部分顺序的结果模块确实取决于向$链接器提供 lib 文件的顺序。

 配置属性 - >链接器 - >额外的依赖关系... 

这里列出的lib文件也是首先在导入部分,意思是,加载程序将按顺序(模数依赖)导入这些。



所以,要回答这一点:只需要向链接器提供正确顺序的lib文件。



注意 :我已经在VS2005上试过了,似乎有效。我不知道这是否记录在某个地方,或者是在较新版本的VC ++中更改。






更新:尽管如此,今天我遇到的情况是加载顺序不是受<$ c的链接器命令行顺序的影响$ c> lib 文件。 (仍然)没有线索为什么。 (Still VS2005)



然而,我已经通过将有问题的DLL添加到延迟加载的DLL列表中(例如在麦克答案)。





Say I have one executable: app.exe

I use 2 different 3rd party DLLs in this executable: foo.dll bar.dll and the Application must link implicitly to these DLLs, that is I cannot use ::LoadLibrary to load them.

(Note: It's not that I cannot call LoadLibrary, but these DLLs require static linking (C++ DLLs with __declspec(dllexport)), so me calling LoadLibrarydoesn't make any sense because the excutable loader has already called it.)

These two DLLs do not have any dependencies on each other, that is, their load order is undefined as far as I can tell (and should be irrelevant). (Dependencies of both are basically only on the standard windows dlls (kernel32, msvcrt, etc.)

I now have the problem that I wish to control the load order of these DLLs, that is I wish that foo.dll is always loaded (DLL_PROCESS_ATTACH) before bar.dll.

Is it somehow possible to tell the Windows DLL Loader to load one DLL before another?

Edit: To check the DLL load order of an executable, one can use the DUMPBIN.exe utility: (Just launch the Visual Studio Command Prompt)

Edit: As per this answer / this blog entry, the NT Loader does walk the import section sequentially. (Which will result in independent DLLs being loaded in the order they appear in the import section.)

C:\path\to\program> dumpbin /IMPORTS app.exe | grep -i \.dll
  MSVCR80D.dll
  KERNEL32.dll
  OLEAUT32.dll
  MSVCP80D.dll
  foo.dll
  bar.DLL

This output means that MSVCR80D.dll (and its dependecies[a]) will be loaded first and that bar.DLL will be loaded last. Unload will happen in reverse order.

What I haven't found out yet is how to influence this load order ...


(Notes)

[a] : This means of course that e.g. kernel32.dll will be loaded first, because msvcr80d.dll will depend on kernel32.dll.


As per some requests, I'm adding a rationale for this: (But please, I'm still interested in this generally. I know how to work around the MFC problem.)

The Microsoft MFC DLL in it's debug version has memory leak detection built in. (As far as I can tell, it's the same mechanism used by _CrtSetDbgFlag and related tools.)

The MFC debug DLL will dump all unfreed memory when it is unloaded. Now, if you have a second DLL in your process, that is independent of MFC, and this second DLL deallocates memory on DLL_PROCESS_DETACH, the MFC reporting mechanism will report false memory leaks, if the MFC DLL is unloaded before the other dll.

If one could make sure that the debug MFC DLL is loaded first / unloaded last of all independent DLLs, then all other DLLs would already have cleaned up after themselves and MFC wouldn't report false leaks.

解决方案

What I haven't found out yet is how to influence this load order ...

I have no clue why I hadn't tried this, but it seems the import section order of the resulting module does depend on the order in which the lib files are provided to the linker.

Configuration Properties -> Linker -> Additional Dependencies ...

The lib files listed here first are also first in the import section, meaning the loader will import these in order (modulo dependencies).

So, to answer that part: Just provide the lib files in the correct order to the linker.

Note: I have tried that on VS2005 and it appears to work. I don't know whether that is documented somewhere or if it changed in newer versions of VC++.


Update: While it worked back then, today I hit the case that the load order was not to be influenced by the linker command line order of the lib files. (Still) No clue why. (Still VS2005)

I have however managed to make it work by adding the problematic DLLs to the list of delay loaded DLLs (like in Macke's answer).


这篇关于更改Windows DLL加载顺序? (加载顺序,不是搜索顺序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆