Поделиться через


Динамическое связывание Run-Time

Когда приложение вызывает функции LoadLibrary или LoadLibraryEx , система пытается найти библиотеку DLL (дополнительные сведения см. в разделе Dynamic-Link Library Search Order). Если поиск выполнен успешно, система сопоставляет модуль DLL с виртуальным адресным пространством процесса и увеличивает число ссылок. Если вызов LoadLibrary или LoadLibraryEx указывает библиотеку DLL, код которой уже сопоставлен с виртуальным адресным пространством вызывающего процесса, функция просто возвращает дескриптор библиотеке DLL и увеличивает число ссылок dll. Обратите внимание, что две библиотеки DLL с одинаковым базовым именем файла и расширением, но размещенные в разных каталогах, не считаются одной библиотекой DLL.

Система вызывает функцию точки входа в контексте потока, который называется LoadLibrary или LoadLibraryEx. Функция точки входа не вызывается, если библиотека DLL уже была загружена процессом через вызов LoadLibrary или LoadLibraryEx без соответствующего вызова функции FreeLibrary .

Если системе не удается найти библиотеку DLL или функция точки входа возвращает значение FALSE, LoadLibrary или LoadLibraryEx возвращает значение NULL. Если LoadLibrary или LoadLibraryEx успешно выполняются, он возвращает дескриптор модулю DLL. Процесс может использовать этот дескриптор для идентификации библиотеки DLL в вызове функции GetProcAddress, FreeLibrary или FreeLibraryAndExitThread .

Функция GetModuleHandle возвращает дескриптор, используемый в GetProcAddress, FreeLibrary или FreeLibraryAndExitThread. Функция GetModuleHandle выполняется успешно, только если модуль DLL уже сопоставлен с адресным пространством процесса путем связывания во время загрузки или предыдущим вызовом LoadLibrary или LoadLibraryEx. В отличие от LoadLibrary или LoadLibraryEx, GetModuleHandle не увеличивает количество ссылок на модуль. Функция GetModuleFileName извлекает полный путь к модулю, связанному с дескриптором, возвращенным командлетами GetModuleHandle, LoadLibrary или LoadLibraryEx.

Процесс может использовать GetProcAddress для получения адреса экспортируемой функции в библиотеке DLL с помощью дескриптора модуля DLL, возвращенного LoadLibrary или LoadLibraryEx, GetModuleHandle.

Если модуль DLL больше не требуется, процесс может вызвать FreeLibrary или FreeLibraryAndExitThread. Эти функции уменьшают число ссылок на модуль и отменяют сопоставление кода DLL из виртуального адресного пространства процесса, если число ссылок равно нулю.

Динамическое связывание во время выполнения позволяет продолжить выполнение процесса, даже если библиотека DLL недоступна. Затем процесс может использовать альтернативный метод для достижения своей цели. Например, если процессу не удается найти одну библиотеку DLL, он может попытаться использовать другую или уведомить пользователя об ошибке. Если пользователь может указать полный путь к отсутствующему dll-файлу, процесс может использовать эти сведения для загрузки библиотеки DLL, даже если она не находится в обычном пути поиска. Эта ситуация контрастирует со связыванием времени загрузки, когда система просто завершает процесс, если не удается найти библиотеку DLL.

Динамическое связывание во время выполнения может вызвать проблемы, если библиотека DLL использует функцию DllMain для инициализации каждого потока процесса, так как точка входа не вызывается для потоков, существовавших до вызова LoadLibrary или LoadLibraryEx . Пример решения этой проблемы см. в статье Использование локального хранилища потока в библиотеке Dynamic-Link.

Использование динамической компоновки во время выполнения