LoadLibrary 的搜索次序
今天写程序的时候发现一个问题,我为 lua 写了一个叫作 console 的 C 扩展库,可老是加载失败。郁闷了好半天后终于找到问题,那就是 lua 解释器实际找到的是 windows/system32 下的一个同名 dll 文件。原来系统也有一个 console.dll 了。
记得从前没有这个问题的,上网查了下 msdn 终于发现其缘故了。原来 windows xp sp2 以后,动态链接库的缺省搜索次序被修改了。
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
Posted by: Linker M Lin | (4) January 24, 2007 10:12 AM
Posted by: zy | (3) December 7, 2006 03:57 PM
Posted by: Atry | (2) December 7, 2006 09:03 AM
Posted by: dreamsun | (1) December 5, 2006 07:14 PM