繁体   English   中英

在所有appdomain中加载的混合模式程序集

[英]Mixed mode assemblies loaded in all appdomains

我们的应用程序设置了一个AppDomain,将一些模块加载到其中。 这些模块之一是使用旧版混合模式DLL与H5文件进行交互。 问题在于,一旦加载了混合模式DLL,就会在新的AppDomain中以及在应用程序启动时创建的原始AppDomain中都放置一个句柄。

当我们卸载该AppDomain时,新AppDomain中的句柄自然会消失,但原始AppDomain中的句柄将保留并固定。 这导致托管堆的碎片化。

在混合模式源代码中找不到任何可以解释此行为的内容。 唯一看起来可疑的是使用本地静态字符串的以下调用:

H5Utils::throwError( String^ message ) {
  String^ stackStr = gcnew String( H5Utils::errorStack_.c_str() );
  String^ myMessage = message + "\n\nError stack: " + stackStr;
  throw gcnew H5IOError( myMessage );
}

其中H5Utils::errorStack_.c_str()是本地静态字符串。 但是,永远不会调用此方法,并且在加载混合模式DLL时,模块会立即加载到两个AppDomain中。

有谁知道为什么要在两个AppDomain中都创建一个句柄?

因此,我进一步研究了这个问题并找到了答案,所以我认为如果有人遇到相同的问题,我会回答我自己的问题。

将模块同时加载到两个AppDomain中的原因是由于使用了本地全局值和静态成员值。 这实际上是有道理的,因为这些值是在本机堆上分配的,并且如果在多个AppDomain中使用此模块,则很有可能您仍然希望共享这些值。

问题是当您不断创建和销毁AppDomain并加载这些类型的资源时,因为首先添加到正在运行的进程AppDomain的引用是静态的,因此会导致固定。 这使托管堆碎片化,长时间运行的进程将开始消耗内存。

为了解决此问题,Microsoft添加了__declspec(appdomain) ,应将其添加到本机类型的全局变量中,以使它们仅驻留在创建模块的AppDomain中。 启用/clr:pure也将使它成为声明。 msdn在appdomain的帮助中对此进行了详细说明

最后的陷阱是,您必须了解#include文件。 例如, #include <string>将导致模块在AppDomain之间共享,而#include <stdio.h>则不会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM