Run-Time动态链接

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

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

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

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

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

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

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

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

使用运行时动态链接