12

Вопрос по appdomain, c# – C ++ DLL не выгружается с AppDomain

У меня есть плагин C #, который использует отдельную C ++ DLL. Единственная ссылка на эту DLL находится внутри самого плагина. Родительское приложение загружает все плагины в свой собственный домен приложений и выгружает этот домен приложений при выгрузке плагина.

Я проверил, и я определенно вижу падение памяти приложения при выгрузке плагина. Я также могу удалить все загруженные управляемые сборки. Проблема в том, что, когда я пытаюсь удалить собственную DLL, я просто получаю Отказ в доступе, пока не закрою все приложение.

Я некоторое время смотрел на это, но до сих пор не могу понять, почему именно эта DLL остается в памяти.

  • 5

    AFAIK (под капотом) родные DLL должны быть загружены через Win32 API

    LoadLibrary... который загружает их непосредственно в память процесса - в случае приложения .NET, которое не является специфичным дляAppDomain... LoadLibrary абсолютно ничего не знает оAppDomain (который является чисто .NET-специфичным) ... таким образом, выгрузкаAppDomain не обязательно выгружать собственные библиотеки DLL ...

    Интересные обсуждения относительно этой ситуации:

    http://clrinterop.codeplex.com/discussions/61817 http://www.mofeel.net/61-microsoft-public-dotnet-framework-interop/1940.aspx

    ЕСЛИ вы можете изменить реализацию соответствующего плагина, то вы бы применили «позднюю нативную привязку»; что бы решить проблему, которую вы видите:

    http://blogs.msdn.com/b/junfeng/archive/2004/07/14/181932.aspx http://www.codeproject.com/KB/cs/dyninvok.aspx http://pinvoke.net/default.aspx/kernel32/GetPRocAddress.html http://www.pinvoke.net/default.aspx/kernel32.loadlibrary

  • 20

    Домены приложений - это чисто управляемая кодовая конструкция. Ничего

    подобного не существует в нативном коде, и Windows не имеет никакого представления об этом. Таким образом, область действия для загруженной нативной библиотеки DLL - это процесс. Технически маршаллер pinvoke может сосчитать количество ссылок на DLL и точно отслеживать, какой AppDomain вызвал загрузку DLL. Однако он не может сказать, работает ли какой-либо нативный код, который использует эту DLL. Собственный код, который может быть запущен вызовом из кода вanother AppDomain, возможно, косвенно через маршалированного делегата.

    Очевидно, что случится беда, если менеджер AppDomain выгружает DLL, которая использовалась таким образом, что неприятно и невозможно диагностировать AccessViolation. Особенно неприятно, так как он может срабатывать долгое время после выгрузки AppDomain.

    Таким образом, маршаллер не реализует этот вид подсчета, DLL остается загруженной. Только вы можете гарантировать, что этого не произойдет, у вас есть определенный контроль над тем, какой код запускается в DLL и как он запускается. Выcan Принудительно выгрузить DLL, но она требует взлома. Pinvoke LoadLibrary () самостоятельно, чтобы получить ручку для DLL. И призовите FreeLibrary ()twice выгрузить его принудительно. Ни Windows, ни CLR не могут видеть, что вы обманываете. Выmust убедитесь, что DLL не может быть использована после этого.