#c #dll #clr
#c #dll #clr
Вопрос:
У меня есть очень простые exe и dll только для тестирования. Вот код в процессе exe:
auto lib = ::LoadLibrary("CppDll.dll");
auto bar = (Bar)::GetProcAddress(lib, "Bar");
bar();
while (::FreeLibrary(lib));
Когда после этого я пытаюсь удалить DLL-файл, я вижу следующее:
Я также заглянул в модули и я озадачен
auto lib = ::LoadLibrary("CppDll.dll");
auto bar = (Bar)::GetProcAddress(lib, "Bar");
bar();
while (::FreeLibrary(lib));
Итак, после вызова bar()
их два. И FreeLibrary
все-таки один остался.
Что я могу сделать, чтобы удалить файл?
UPD: Я только что обнаружил, что это происходит только в том случае, если dll поддерживает clr.
Ответ №1:
Это кажется невозможным. Приложение, в котором размещается среда CLR, использует CLRCreateInstance
, из которого оно может получить ICLRMetaHost
интерфейс, по которому оно может вызывать GetRuntime
для создания среды CLR. Но в интерфейсе нет членов для выгрузки CLR. Его Stop
метод останавливает выполнение кода в CLR, но не освобождает, не выделяет ресурсы и не выгружает домены приложений. Но чтобы выгрузить сборку, мы должны выгрузить все домены приложений, которые ее используют.
Итак, чтобы иметь возможность выгружать сборку, нужно загрузить ее в отдельный домен приложения, а затем выгрузить домен приложения. Но невозможно выгрузить DLL, которая загружает CLR, CLR может быть выгружена только при завершении процесса.
Richter, CLR через C #. Глава 22 «Хостинг CLR и домены приложений»:
Первый домен приложения, созданный при инициализации среды CLR, называется доменом приложения по умолчанию; этот домен приложения уничтожается только при завершении процесса Windows.