多次加载一个DLL?

9
我正在使用LoadLibrary函数在Windows中加载DLL。我的问题是:如果我多次为同一个DLL调用此方法,我会得到指向不同实例的句柄,还是它们都将指向同一实例?
此外,这种行为与Linux SO文件有何关联,是相同还是完全不同的,我可以在这方面做出什么样的假设?谢谢。

你想要一个独立的 DLL 实例(及其全局状态)吗? - David Heffernan
@DavidHeffernan 可能吗,但只有在Linux上也可以完成。我更想掌握事情通常是如何运作的。如果您所描述的是可能的,我很想知道如何做到这一点。 - Liam M
1
在操作系统中,它的工作方式是相同的。有一个诡计可以获得DLL的单独实例。每次需要新实例时,将文件复制到临时位置并赋予其唯一名称。这样,您就可以强制系统加载新模块。我有时使用这种技术来解决由于设计不良和全局状态的使用而导致的线程不安全的库问题。 - David Heffernan
请注意,文件的路径并不是决定性因素,而是文件名来进行标识。@DavidHeffernan - Polynomial
@polynomial并不完全正确。在不同文件夹中加载同名的两个DLL将导致加载两个不同的模块。我认为你所说的是16位Windows的情况。 - David Heffernan
@DavidHeffernan - 抱歉,事实证明是谷歌把 Windows CE 文档发送给了我:http://msdn.microsoft.com/en-us/library/ms886736.aspx - Polynomial
3个回答

12

MSDN文档说明:

系统对所有已加载的模块维护一个每进程引用计数。调用LoadLibrary会增加引用计数。调用FreeLibrary或FreeLibraryAndExitThread函数会减少引用计数。当模块的引用计数达到零或进程终止(无论引用计数如何),系统将卸载该模块。

因此,似乎多次加载模块(没有匹配的FreeLibrary调用)将返回相同的句柄。


3
如果DLL已经被加载,LoadLibrary将只返回内存中库的地址。然而,当尝试进行第二次加载时,DllMain不会再次使用DLL_PROCESS_ATTACH调用。在库的意义上,句柄只是内存位置,所以第二次得到的值应该与第一次相同。
就Linux SO文件而言,我不明白为什么它们会加载两次。然而,其他人需要参与讨论并给出正确答案。

3

对于Linux共享对象,参考dlopen(3)手册

如果使用dlopen()再次加载相同的库,则返回相同的文件句柄dl库为库句柄维护引用计数,因此只有在dlopen()成功调用的次数等于dlclose()调用的次数时,动态库才会被释放。如果存在,则_init()例程仅调用一次。但是,使用RTLD_NOW进行的后续调用可能会强制解析先前使用RTLD_LAZY加载的库的符号。


这是针对每个进程还是所有进程? - g19fanatic
@g19fanatic - 对于同一进程。 - cha0site
1
对于Linux,您可以使用dlmopen()函数。 - Eytan Naim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接