« 墨攻 | 返回首页 | 在 Windows 下使用 Timer 驱动游戏 »

LoadLibrary 的搜索次序

今天写程序的时候发现一个问题,我为 lua 写了一个叫作 console 的 C 扩展库,可老是加载失败。郁闷了好半天后终于找到问题,那就是 lua 解释器实际找到的是 windows/system32 下的一个同名 dll 文件。原来系统也有一个 console.dll 了。

记得从前没有这个问题的,上网查了下 msdn 终于发现其缘故了。原来 windows xp sp2 以后,动态链接库的缺省搜索次序被修改了。

Dynamic-Link Library Search Order

windows XP 以及 windows 2000 sp4 以后,windows 在注册表中加了一项:

HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

用来增加 DLL 加载的安全性,刚开始,这个选项是被缺省关闭的。但是在 xp sp2 以后,估计是 ms 中的某人觉得时机到了,就把这个选项缺省打开了。(我估计很少人会主动去在注册表里改这个东西,所以缺省关闭跟没有这个东西几乎没有区别)

有了这个设置后,当前目录被放在了搜索次序的优先级最低位。所以只要不小心跟系统的 dll 重名, lua 的 require 指令便不能正确的找到当前路径下的 dll 文件了。就算你明确写明 .\console.dll 也没折(lua 的 require 系统就是这样做的),从当前目录推导相对路径的优先级依然是最低的。

解决这个问题的最佳方案是修改 lua 的源码,把 loadlib.c 中第 128 行的

HINSTANCE lib = LoadLibrary(path);

改成 LoadLibraryEx 即可:

HINSTANCE lib = LoadLibraryEx(path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);


补充:经过一些讨论,发现 MS 在 DLL 搜索次序上的补救措施是很有道理的。因为所谓当前路径是一个很不安全的地方。甚至一次打开文件的对话框都有可能改变它。所以在当前路径上加载代码完全是一种冒险。

建议 lua 把所有依赖相对当前的路径的地方都改成依赖程序启动时的绝对路径。这个问题不仅仅是对 DLL 的,而是对所有可执行代码的。

Comments

终于明白了,上个月调试的时候,遇到这个问题了。
to Atry 看看msdn的文章吧 加载次序第一个就是The directory from which the application loaded.
手动LoadLibrary是没问题,但是如果链接到DLL是隐式的在导出段做的话,有什么办法能够让他从程序所在目录而不是当前目录加载呢?
我在使用DirectX9.0c版本的时候,用dsound和dinput时候总会出现一些BUG,不能正常运行,但是把其中的库文件换成2002版本后就可以正常运行了.不知是新版本的问题还是我的无知?请云风大哥指教!

Post a comment

非这个主题相关的留言请到:留言本