【问题标题】:Is there a best practice of loading a DLL from within another DLL?是否有从另一个 DLL 加载 DLL 的最佳实践?
【发布时间】:2012-09-07 15:16:55
【问题描述】:

我需要从另一个 DLL 中加载一个 DLL。诱惑是在 DllMain 中加载它,但已经有令人信服的文档说这是一个“坏主意”。

冒着问一个不太具体的问题的风险:是否有从另一个 DLL 加载 DLL 的最佳实践?

在我们当前的项目中,我们的主 DLL 有一个类。我从该类的构造函数加载第二个 DLL。但是,由于该类可以在 DLL 中多次实例化,因此我保留了一个变量来指示 DLL 之前是否已加载,以免再次调用 LoadLibrary。不知何故,这似乎不是一个好的解决方案,因此我提出了问题。

【问题讨论】:

  • 就其价值而言,您的解决方案一点也不差——它非常普遍。这是解决此问题的一种简单优雅的方法,无需在 DLL 中强加一些额外的初始化函数。我会把它放在像EnsureOtherDLLLoaded 这样的函数中。
  • 您的解决方案很好。事实上,您甚至不必跟踪它是否已经加载。在该过程中再次调用 LoadLibrary 就可以了。 Windows 将保留库的引用计数,并且在 FreeLibrary 调用的数量与 LoadLibrary 调用的数量匹配之前不会卸载它。

标签: c++ visual-studio-2010 dll


【解决方案1】:

这取决于您的 DLL。 基本上,您有以下选择:

  1. 链接到该 DLL 的 LIB 以自动加载它
  2. 在加载库时加载其他 DLL,在卸载之前先卸载
  3. 使用前加载其他 DLL,然后卸载

如果您选择 1,您将收到非常奇怪的消息,如果在您尝试加载 DLL1 时缺少 DLL2,例如“加载 DLL1 失败”。而且客户永远不会知道这是因为缺少 DLL2。所以我不喜欢使用这个解决方案,如果你不能 100% 确定 DLL2 是否正确安装。

但是,当您手动加载 DLL2 (LoadLibrary) 时,您有机会呈现有意义的消息。

如果您的 DLL 中有明确的入口和出口点,您可以选择 2。如果您的 DLL 导出一个或很少的函数,即为其他对象创建工厂的函数,就会出现这种情况。然后就可以用工厂加载/卸载了。

如果这不会导致您频繁执行此加载/卸载,您可以选择 3。

此外,您无需只保留一个 DLL2 句柄。您可以多次调用 LoadLibrary/FreeLibrary,由框架进行引用计数。

因此,在您的情况允许的情况下,您可以选择这 3 种解决方案中的一种。只有当您没有明确的入口点并且您经常调用需要 DLL2 的函数时,您才必须使用原始解决方案。

【讨论】:

  • 听起来你是在告诉他他可以随意多次使用 LoadLibrary,从 0 开始递增一个变量,框架将为他进行引用计数,并且不会有很大的开销。然后在退出时,调用 FreeLibrary 的次数与变量增加的次数一样多。
  • 当然有一些开销,但是相对来说比较小。我刚刚检查过:第二个 LoadLibrary 返回与第一个 (p1) 相同的指针 (p2)。所以该库没有第二次加载,只是重复使用了相同的问题。然后你可以 FreeLibrary(p2) 并继续使用 p1。当然,加载和卸载的总数应该匹配。
  • 第二个 LoadLibrary 是否会导致第二个 DLLMain 被第二次执行?
  • @std''OrgnlDave 没有。这里的另一个选项是GetModuleHandle,以查看 DLL 是否已加载。
猜你喜欢
  • 2013-04-21
  • 2011-08-12
  • 1970-01-01
  • 2012-03-23
  • 2015-07-14
  • 2010-10-14
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
相关资源
最近更新 更多