У вас будет утечка ручки в случае:
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.