【问题标题】:Delphi: Odd behaviour loading DLLs with LoadLibraryDelphi:使用 LoadLibrary 加载 DLL 的奇怪行为
【发布时间】:2014-02-06 23:05:48
【问题描述】:

我正在使用 Delphi 构建一个插件系统(你们中的一些人一直在帮助我完成这项任务)。

为了搜索 DLL 文件,我使用了 TSearchRec,它在 exe 路径中搜索 dll 文件,然后我使用 LoadLibrary 来访问它们。 然后,如果某个函数被公开(使用 GetProcAddress),我将它作为插件加载。如果不是,则执行 FreeLibrary,并继续执行下一个文件。

在测试时,我注意到当 TSearchRec 找到恰好在该路径中的“borlndmm.dll”时,它会加载并搜索我的插件函数,当然没有找到,但是当 if 执行 FreeLibrary ,我遇到访问冲突。

同一路径中的其他无插件 dll,例如 libmariadb.dll,可以安全地释放而不会出错。

当然,这很容易解决,方法是将我的插件 dll 放在自己的路径中,没有任何其他 dll 文件,即使出于性能原因,这也会更好,因为它不必加载任何不应该加载的库.

但我想了解它为什么会发生。 有什么想法吗?

谢谢 努诺·皮卡多

【问题讨论】:

  • 不要将随机 DLLS 加载到您的进程中。真是个坏主意。
  • 如果您创建一个测试应用程序,除了在borlndmm.dll 上调用LoadLibrary,然后调用FreeLibrary,这还会发生吗?如果是这样,请发布使用的代码。如果不是,这是一个与您的应用程序本身隔离的问题。 (我同意@DavidHeffernan,顺便说一句;将随机 DLL 加载到您的进程中是一个糟糕的主意。)
  • 谢谢大卫和肯。我会听从这个建议的!
  • 我做过一个非常相似的项目,几乎完全按照您的描述进行。我避免加载不应该加载的 DLL 的方法是给它们一个唯一的文件扩展名。这样,您只能搜索具有您决定为其提供的任何唯一扩展名的文件。这些文件也应该位于它们自己的文件夹中 - 不与您的其他程序文件混合,而是在子文件夹中。
  • 只是一个警告,在没有 100% 确定您可以控制内容的情况下,永远不要加载 DLL。这是病毒或恶意软件在计算机上启动和运行的最简单方法之一。我会添加一个配置文件,指定包含哪些 DLL,然后按照 Jerry 的建议更改名称,然后还包含某种签名以确保它是您的 DLL。

标签: delphi dll access-violation


【解决方案1】:

为什么您遇到某些 DLLS 问题的原因是因为 LoadLibrary 在它加载的 DLL 中执行代码 - 特别是 DLL 的初始化代码。在 Delphi 项目中,这包括单元初始化部分。在 borlandmm.dll 的情况下,dll 初始化代码将自己插入到您的主机 exe 进程的运行时库中,用 DLL 中的内存管理器替换您的默认内存管理器。这不是一个可逆的动作——它不能在 DLL 关闭代码中删除自己(部分原因是 DLL 关闭代码不能保证在所有情况下都执行)。

所以,使用 LoadLibrary 时要小心,因为在您知道 DLL 是什么之前,您基本上是在执行任意代码。如果您确实必须查看大量来源不明的任意 DLL,则更安全的方法是将 DLL 作为资源映像而不是可执行映像加载。这会将文件加载到内存中,但不会执行 DLL 初始化代码。请参阅 LoadLibraryEx() 和 LOAD_LIBRARY_AS_IMAGE_RESOURCE 标志。

正如您在前面的评论中提到的,您可以采取许多措施来减少您需要加载的 DLL 的数量,使其正好符合用户/管理员希望您的应用程序加载的 DLL,而不是加载您需要的所有内容。可以找到。

  1. 要求 DLL 文件名具有自定义扩展名或文件名模式。 (例如插件*.mod)
  2. 仅从特殊子目录加载 DLL。这适用于目录级访问控制,因为在大多数系统上,bin 目录对于普通用户是不可写的。必须有管理员权限才能将 DLL 放入特殊子目录。
  3. 仅加载在用户定义的配置文件中命名的 DLL 文件。
  4. 以上任意组合

【讨论】:

  • 谢谢 dthorpe。我使用名称、子目录和版本信息“签名”技术确保只有真正的系统插件才会传递给 LoadLibrary。
【解决方案2】:

该 DLL 实现了一个共享内存管理器。它设计为仅与加载时间链接一起使用。它由加载程序加载,并且在进程结束之前永远不会卸载。一旦它被加载,它就会对进程的所有未来堆分配和释放负责。所以它改变了宿主进程的行为。它不能动态加载。

故事的寓意是不要将随机 DLL 加载到您的进程中。仅加载您或您的程序用户特别要求加载的 DLL。

【讨论】:

  • 再次感谢大卫。这就解释了。所以,由于在这种情况下我无法提前知道它应该加载哪个 dll,我就让它由用户负责。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多