Будет ли удалена библиотека DLL, если загруженная библиотека DLL выгружена? - PullRequest
8 голосов
/ 05 марта 2009

Взять стандартное приложение Windows. Он загружает DLL, используя LoadLibrary для вызова функции в нем (мы будем называть это DLL_A). Эта функция загружает другую DLL (назовем ее DLL_B). Приложение теперь выгружает DLL_A DLL, используя FreeLibrary, так как она больше не требуется.

Вопрос в следующем: DLL_B все еще находится в памяти и загружен?

Это то, от чего я могу зависеть, или это недокументировано?

Ответы [ 4 ]

11 голосов
/ 05 марта 2009

Нет. DLL_B не будет выгружено. Вызов LoadLibrary(), сделанный DLL_A, увеличит счет загрузки для DLL_B. Поскольку для DLL_B нет соответствующего FreeLibrary() вызова, пересчет не будет равен нулю.

Из документации LoadLibrary ():

Система поддерживает процесс счетчик ссылок на все загруженные модули. Вызов LoadLibrary увеличивает счетчик ссылок Вызов FreeLibrary или Функция FreeLibraryAndExitThread уменьшает счетчик ссылок. система выгружает модуль, когда его счетчик ссылок достигает нуля или когда процесс завершается (независимо от счетчик ссылок).

3 голосов
/ 05 марта 2009

У вас будет утечка ручки в случае:

Program -Load> Dll A 
          -Load> Dll B 
        -Unload> Dll A

Никакой код не выполняется неявно модулем, который выгружается для выгрузки загруженных модулей.

Поскольку для уменьшения количества ссылок код не выполняется, модуль B никогда не будет выгружен.

Вот правила загрузки / выгрузки dll:

  • Каждый вызов LoadLibrary и LoadLibraryEx будет увеличивать счетчик ссылок для этого модуля. Это только в контексте вызывающего процесса, но не за его пределами.
  • Каждый вызов FreeLibrary или FreeLibraryAndExitThread уменьшает счетчик ссылок.
  • Когда счетчик ссылок достигнет 0, он будет выгружен.
  • Когда Windows увидит, что ваша программа закрыта , все утечки выгруженных модулей будут выгружены.
  • В зависимости от того, что вы делаете, DllCanUnloadNow может быть вам полезно.

Все еще в памяти и все еще загружен:

Нет гарантии, что ваш модуль будет освобожден из памяти в определенное время, когда ссылка достигнет 0. Но вы должны рассматривать модуль так, как будто он выгружен, когда счетчик ссылок достигает 0.

Остановка DLL от выгрузки:

Чтобы выгрузить библиотеку DLL, вы можете попробовать

  • Система вызывает DllMain с флагом DLL_PROCESS_DETACH. Вы можете попытаться не вернуться из этого с помощью какой-либо операции блокировки.
  • Вы можете попытаться вызвать LoadLibrary из библиотеки DLL, которую вы не хотите выгружать. (Самостоятельная загрузка)

Редактировать:

Вы упомянули, что ваша цель состоит в том, чтобы внедрить код в работающую программу и что вы хотели утечку дескриптора специально.

Это хорошо, но если вы часто запускаете эту операцию, это может привести к сбою в исходной программе, поскольку будет использоваться слишком много дескрипторов или в конечном итоге будет использоваться слишком много памяти.

Вы можете вернуть FALSE из DllMain, чтобы остановить его загрузку, чтобы не тратить впустую память. Вы делаете это, когда fdwReason имеет значение DLL_PROCESS_ATTACH. Вы можете узнать больше об этом здесь .

Если вы пытаетесь эмулировать DLL и добавлять свои собственные дополнительные функции, вам нужно будет реализовать все функции, которые реализует исходная DLL, и делегировать каждый обратный вызов исходной DLL.

1 голос
/ 05 марта 2009

DLL в окнах подсчитываются. Когда A выгружается, вы уменьшаете счетчик ссылок на A, если он достигает нуля, он выгружается, и (при условии отсутствия ошибок в коде) уменьшает счетчик ссылок на B. Если счетчик ссылок на B обращается в ноль, он будет выгружен , Возможно, DLL C имеет счет на B, и выгрузка A не будет выгружать B.

1 голос
/ 05 марта 2009

Прочитайте раздел Замечания для подробного объяснения.

Ключевой момент, на который следует обратить внимание:

Система поддерживает счетчик ссылок для каждого загруженного модуля

и далее вниз

Когда счетчик ссылок модуля достигает нуля или процесс завершается, система выгружает модуль из адресного пространства процесса

С MSDN :

Освобождает загруженный модуль динамически подключаемой библиотеки (DLL) и, при необходимости, уменьшает его счетчик ссылок. Когда счетчик ссылок достигает нуля, модуль выгружается из адресного пространства вызывающего процесса, и дескриптор больше не действителен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...