Run-Time动态链接

当应用程序调用 LoadLibraryLoadLibraryEx 函数时,系统会尝试查找 DLL (以了解详细信息,请参阅 动态链接库搜索顺序) 。 如果搜索成功,系统会将 DLL 模块映射到进程的虚拟地址空间,并递增引用计数。 如果对 LoadLibraryLoadLibraryEx 的调用指定了一个 DLL,该 DLL 的代码已映射到调用进程的虚拟地址空间中,则函数仅返回 DLL 的句柄并递增 DLL 引用计数。 请注意,具有相同基本文件名和扩展名但位于不同目录中的两个 DLL 不被视为同一 DLL。

系统在调用 LoadLibraryLoadLibraryEx 的线程上下文中调用入口点函数。 如果进程已通过对 LoadLibrary 或 LoadLibraryEx 的调用加载了 DLL,但没有对 FreeLibrary 函数的相应调用,则不会调用入口点函数。

如果系统找不到 DLL 或入口点函数返回 FALSE, 则 LoadLibraryLoadLibraryEx 返回 NULL。 如果 LoadLibraryLoadLibraryEx 成功,它将返回 DLL 模块的句柄。 进程可以使用此句柄在调用 GetProcAddressFreeLibraryFreeLibraryAndExitThread 函数时标识 DLL。

GetModuleHandle 函数返回 GetProcAddressFreeLibraryFreeLibraryAndExitThread 中使用的句柄。 仅当 DLL 模块已通过加载时链接或先前调用 LoadLibrary 或 LoadLibraryEx 映射到进程的地址空间时,GetModuleHandle 函数才会成功。LoadLibraryLoadLibraryEx 不同, GetModuleHandle 不会递增模块引用计数。 GetModuleFileName 函数检索与 GetModuleHandleLoadLibraryLoadLibraryEx 返回的句柄关联的模块的完整路径。

进程可以使用 GetProcAddress 通过 LoadLibrary 或 LoadLibraryExGetModuleHandle 返回的 DLL 模块句柄获取 DLL 中导出函数的地址。

当不再需要 DLL 模块时,进程可以调用 FreeLibraryFreeLibraryAndExitThread。 如果引用计数为零,这些函数会递减模块引用计数,并从进程的虚拟地址空间取消映射 DLL 代码。

运行时动态链接使进程能够继续运行,即使 DLL 不可用也是如此。 然后,该过程可以使用替代方法来实现其目标。 例如,如果一个进程找不到一个 DLL,它可以尝试使用另一个 DLL,或者它可能会通知用户出错。 如果用户可以提供缺少的 DLL 的完整路径,则进程可以使用此信息加载 DLL,即使它不在正常的搜索路径中。 这种情况与加载时链接形成鲜明对比,在该链接中,如果系统找不到 DLL,系统只会终止进程。

如果 DLL 使用 DllMain 函数对进程的每个线程执行初始化,则运行时动态链接可能会导致问题,因为不会对调用 LoadLibrary 或 LoadLibraryEx 之前存在的线程调用入口点。 有关如何处理此问题的示例,请参阅 在Dynamic-Link库中使用线程本地存储

使用运行时动态链接