首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LoadLibrary似乎加载错误的DLL

LoadLibrary似乎加载错误的DLL
EN

Stack Overflow用户
提问于 2012-06-19 12:24:46
回答 1查看 2.5K关注 0票数 1

我在Windows上使用LoadLibrary有一个奇怪的问题。首先是一些背景。这个应用程序依赖于Qt,Qt被分成几个库。我试图升级Qt的版本,但没有破坏任何人。新的Qt库与旧的Qt库向后兼容。这意味着,使用旧版本构建的应用程序如果加载更新版本,就可以运行。相反的情况并非如此--如果加载旧版本,使用更新版本构建的应用程序将缺少符号。

Qt位于特定于版本的目录中(例如c:\qt\qt-4.5.2\libc:\qt\qt-4.8.1\lib )。大多数开发人员的路径中也有一个公共目录,其中包含我们使用的所有第三方库(称为c:\common\lib)的“当前”版本。在运行应用程序时,通常会在这里找到Qt库。

我将新的Qt版本库放在公共位置,除了一种情况外,一切似乎都正常。所讨论的应用程序被分成多个库,其中一些库是通过调用LoadLibrary()加载的。其中一些运行时加载的DLL依赖于Qt库。在一种情况下,加载的DLL依赖于QtXml,而后者本身依赖于QtCore

这是奇怪的地方。应用程序依赖于QtCore,也加载依赖于QtXml的库。应用程序和库是与旧版本的Qt连接而成的。如果此应用程序仅在路径中的公共目录下运行,则所有操作都正常,因为新的Qt版本DLL是从公共目录加载的。但是,如果路径包含存储在公共目录之前的旧Qt版本DLL的目录,则加载运行时DLL时将失败,缺少符号。

(在进行自动化单元测试时会出现这种情况,脚本将显式设置使用特定库版本的路径。)

据我所知,应用程序正在加载旧版本的QtCore.dll,运行时加载的DLL正在加载新版本的QtXml.dll,这是因为已经加载的QtCore没有它需要的符号而失败。

但这似乎是不可能的,因为路径类似于c:\qt\qt-4.5.2\lib;c:\common\lib (加上其他不相关的路径)。如果我从公共lib目录中删除更新的QtXml (不是用旧版本替换它,只需删除它),那么LoadLibrary()就成功了,因为它加载了所有Qt库的4.5.2版本。但这不是一个好的长期解决方案,因为在PATH (公共)中没有Qt特定版本目录的情况下运行将无法找到QtXml

这怎么可能是?LoadLibrary() (或者它递归调用以解决库的依赖关系)如何从PATH的后面加载一个库?我找不到任何能表明对公共库目录给予特殊考虑的东西(它不是一个设置的DLL目录)。在构建过程中没有提到这一点,这只是开发人员在他们的PATH中为了方便而拥有的东西。

顺便说一句,在LD_LIBRARY_PATHdlopen()的Linux上也存在类似的情况,而且它在那里工作得很好。这是Windows正在做的不一样的事情,我不明白。有没有人对可能出的问题有任何洞察力?

EN

回答 1

Stack Overflow用户

发布于 2012-06-19 13:16:45

LoadLibrary有很多令人惊讶的行为。确保您在MSDN中对所有的备注进行了充分的摸索。

如果已经加载了一个具有相同名称的库(任何版本),LoadLibrary只会返回一个已加载DLL的句柄。这可能会在你的场景中起作用。

接下来,如果您指定了一个相对路径或仅指定了一个文件名,LoadLibrary将应用神秘搜索规则。路径变量通常是搜索的最后一个位置。其他一些规则很可能是在检查路径之前找到“错误”DLL。一个好的指导方针是始终使用一个绝对路径--您想要加载的文件--以确保它的搜索规则不会捕获错误的文件。一个常见的安全漏洞是不控制LoadLibrary搜索的位置,攻击者说服应用程序加载修改后的DLL。

最后,安装程序可以应用DLL重定向,它可以覆盖您所要求的内容以及它的位置。我不确定这对于Qt是否常见,但是您可能需要检查您的注册表。

我偶尔会在程序加载DLL时使用ProcMon来自SysInternals来观察它。你可以看到它检查的每一个地方,这可能会给你一个线索,为什么它会找到错误的版本。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11100867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档