如果我使用 Win32 API LoadLibrary连续 3 次加载相同的 DLL,它应该返回 3 个不同的句柄,并且每个库中的函数都应该有不同的地址,对吗?(或者它是否做了一些“聪明”的事情并检测是否已经为进程加载了 dll 并只是指向同一个模块?)
3 回答
它做了一些聪明的事情。Windows 为通过 LoadLibrary 加载的每个 DLL 保留一个引用计数。这就是为什么您必须为每个相应的 LoadLibrary 调用调用一次 FreeLibrary。假设您不首先释放 DLL,每次调用 LoadLibrary 都会为您提供相同的句柄。
来自 FreeLibrary 的 MSDN 文档:
每个进程为每个加载的库模块维护一个引用计数。此引用计数在每次调用 LoadLibrary 时递增,并在每次调用 FreeLibrary 时递减。
如果它们是相同的 DLL,则不会再次加载它。
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx
“如果指定的模块是一个尚未为调用进程加载的 DLL,则系统使用 DLL_PROCESS_ATTACH 值调用该 DLL 的 DllMain 函数。如果 DllMain 返回 TRUE,LoadLibrary 返回模块的句柄。如果 DllMain 返回 FALSE,系统从进程地址空间卸载 DLL,LoadLibrary 返回 NULL。从 DllMain 调用 LoadLibrary 是不安全的。有关详细信息,请参阅 DllMain 中的备注部分。
“如果 lpFileName 不包含路径并且有多个加载的模块具有相同的基本名称和扩展名,则该函数返回第一个加载的模块的句柄。”
不,它没有。为了解决这个问题,您可以将 .dll 复制到一个临时文件中(根据需要多次加载 .dll),然后在完成后删除这些文件。