Delphi:使用LoadLibrary加载DLL的奇怪行为

nun*_*ado 1 delphi dll access-violation

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

要搜索DLL文件,我正在使用TSearchRec,它在dll文件的exe路径中搜索,然后我使用LoadLibrary来访问它们.然后,如果暴露某个函数(使用GetProcAddress),我将其作为插件加载.如果没有,则执行FreeLibrary,然后继续下一个文件.

在测试的时候,我注意到当TSearchRec找到了"borlndmm.dll"时,它恰好在那个路径中,它加载,并搜索我的插件函数,当然没有找到,但是如果执行FreeLibrary,我得到访问冲突.

其他no-plugin dll在同一路径中,如libmariadb.dll,可以安全地释放,没有错误.

当然,这很容易修复,让我的插件dll在自己的路径中,没有任何其他dll文件,这甚至出于性能原因会更好,因为它不必加载任何它不应该的库.

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

谢谢Nuno Picado

dth*_*rpe 5

究其原因,为什么你遇到了一些DLL时出现问题是因为调用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. 以上任意组合