C ++ DLL不会使用AppDomain卸载
我有一个使用单独的C ++ DLL的C#插件。 对该DLL的唯一引用来自插件本身。 父应用程序将所有插件加载到自己的AppDomain中,并在卸载插件时卸载此AppDomain。
我已经检查了,当我卸载插件时,我肯定会看到应用程序的内存丢失。 我还能够删除所有已加载的托管程序集。 问题是,当我尝试删除本机DLL时,我只是继续拒绝访问,直到我关闭整个应用程序。
我已经看了一段时间,但我仍然无法弄清楚为什么这个DLL留在内存中。
AppDomains是纯托管代码构造。 本机代码中不存在任何类似内容,Windows也不了解它。 因此加载的本机DLL的范围就是进程。 从技术上讲,pinvoke marshaller可以引用计数DLL并准确跟踪哪个AppDomain触发了DLL的加载。 然而,它无法判断是否正在运行使用该DLL的本机代码。 可以通过另一个 AppDomain中的代码调用启动的本机代码,可能通过封送委托间接调用。
如果AppDomain管理器卸载以这种方式使用的DLL,那将是一个令人讨厌且无法诊断AccessViolation的灾难。 特别讨厌,因为它可以在AppDomain卸载后触发很长时间。
所以marshaller没有实现那种计数,DLL保持加载状态。 只有您可以保证不会发生这种情况,您可以控制DLL中运行的代码以及它如何启动。 你可以强制DLL卸载但它需要一个hack。 Pinvoke LoadLibrary()自己来获取DLL的句柄。 并且两次使用 FreeLibrary()来强制卸载它。 Windows和CLR都看不到你在作弊。 您必须确保在此之后无法使用DLL。
AFAIK(引擎盖下)本机DLL需要通过Win32 API LoadLibrary
加载…它将它们直接加载到进程内存中 – 如果.NET应用程序不是特定于AppDomain
… LoadLibrary
绝对不知道AppDomain
(纯粹是特定于.NET)…因此卸载AppDomain
不一定卸载本机DLL …
关于这种情况的有趣讨论:
如果您可以更改相应插件的实现,那么您将实现“晚期本机绑定”,这将解决您看到的问题:
上述就是C#学习教程:C ++ DLL不会使用AppDomain卸载分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1013536.html