【发布时间】:2011-09-16 08:08:01
【问题描述】:
假设我有一个可执行文件:app.exe
我在这个可执行文件中使用了 2 个不同的第 3 方 DLL:foo.dllbar.dll,并且应用程序必须隐式链接到这些 DLL,也就是说我不能使用 ::LoadLibrary 来加载它们。
(注意:不是我不能调用LoadLibrary,而是这些DLL需要静态链接(带有__declspec(dllexport)的C++ DLL),所以我调用LoadLibrary没有任何意义,因为可执行加载程序已经调用它。)
这两个 DLL 确实 彼此之间没有任何依赖关系,也就是说,据我所知,它们的加载顺序是未定义的(并且 应该 是不相关的)。 (两者的依赖基本上都只在标准的windows dll(kernel32、msvcrt等)上
我现在有一个问题,我希望控制这些 DLL 的加载顺序,即我希望 foo.dll 在 bar.dll 之前始终加载 (DLL_PROCESS_ATTACH)。
是否有可能告诉 Windows DLL 加载程序先加载一个 DLL?
编辑:要检查可执行文件的 DLL 加载顺序,可以使用 DUMPBIN.exe 实用程序:(只需启动 Visual Studio 命令提示符)
编辑:根据this answer / this blog entry,NT 加载器确实按顺序遍历导入部分。 (这将导致 独立 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 将最后加载。卸载将以相反的顺序进行。
我还没有发现如何影响这个加载顺序 ...
(注释)
[a] :这当然意味着例如kernel32.dll 会先加载,因为 msvcr80d.dll 会依赖 kernel32.dll。
根据一些要求,我为此添加了一个理由:(但是请,我仍然对此一般感兴趣。我知道如何解决 MFC 问题。)
它的调试版本中的 Microsoft MFC DLL 内置了内存泄漏检测。(据我所知,它与 _CrtSetDbgFlag 和相关工具使用的机制相同。)
MFC 调试 DLL 将在卸载时转储所有未释放的内存。现在,如果您的进程中有第二个 DLL,它独立于 MFC,并且这个第二个 DLL 在 DLL_PROCESS_DETACH 上释放内存,如果 MFC DLL 在另一个 dll 之前卸载,则 MFC 报告机制将报告错误的内存泄漏。
如果可以确保调试 MFC DLL 在所有独立 DLL 中最先加载/最后卸载,那么所有其他 DLL 本身就已经清理完毕,并且 MFC 不会报告错误泄漏。
【问题讨论】:
-
您的编辑不正确。当然
kernel32.dll不会在低级 CRT DLL (msvcr*.dll) 之后加载:P 你可以使用ProcMon 或 WinDbg 来查找。 -
@Martin Dumpbin 未按加载顺序列出其导入。我不知道你是从哪里得到这个想法的。
-
@David:根据其他问题答案中的MS blog linked to,Loader 实际上确实按顺序遍历导入表。
-
@David:我需要多久重复一次independent这个词?
-
@Martin 现在问题好多了,因为您已经给出了一些上下文并解释了为什么要影响加载顺序。我认为你最大的问题是你不明白我们喜欢被这种理由所激励。即使在您的编辑中,您也非常不情愿地给出问题背后的原因。不要那样。告诉我们你问这个问题的原因。你提供的信息越多,你的潜在回答者就越有动力,你可能会得到更好的答案。既然你的问题很清楚,例如,我删除了我的答案。