2010-03-26 60 views
3

我有一个外部(.Net)dll,我必须用于应用程序。不幸的是,该DLL有几个已知的内存泄漏。我们正在努力让dll的作者修复内存泄漏,但同时我想知道什么是最好的方式来使用dll而不必处理内存泄漏?如何处理外部DLL中的内存泄漏

回答

3

将.Net程序集移动到它自己的AppDomain中,以便您可以定期卸载模块可能有助于在泄漏是由于挂在对象引用“太长”,但大部分“内存泄漏”的情况下遇到.Net托管代码实际上未能释放非托管资源句柄 - 释放句柄,关闭文件,关闭网络连接等。

如果资源由一个负责任的.net托管对象所拥有,该托管对象在IDispose.Close中释放其非托管句柄(),但是某些骨头代码在它应该执行GC循环或卸载程序集的AppDomain时不会调用IDispose.Close,可能会通过“快速”处理拥有的管理对象的最终GC来帮助回收这些孤立的非托管资源。

如果句柄属于完全不能正确释放它们的骨头代码,卸载程序集的AppDomain不太可能有助于回收孤立的句柄。

当进程终止时,与句柄关联的大多数Windows资源将被恢复。这有点极端,但如果GC和AppDomain循环不起作用,您可以编写一个封装器来讨论有问题的.NET程序集类,并使用.NET远程处理来彻底抛弃程序中的违规程序集。在违规程序集的类和其他应用程序之间进行多少数据交互将决定这是否完全可行。如果违规程序集相当独立并且有少量的接口入口点,那么这可能是可行的。在违规组装过程中,您可以定期关闭它以清除累积的垃圾,而不必关闭自己的过程。

绝对保留绝对最后手段的最后一个想法。尝试找出哪种内存或资源正在泄漏以及泄露的方式以及AppDomain循环是否会回收丢失的资源。

+0

特别是这个DLL打开一个SqlConnection,并且从不关闭它。 – Dugan 2010-03-26 14:32:52

2

除非被混淆,否则使用.NET Reflector并取出代码,找到相关部分,修复它,重新编译它,然后使用重新编译的代码。

这可能会或可能不适合您的环境。当我必须弄清楚如何与一些供应商的东西进行交互时,如果他们拒绝我的文档,我就适用。但请记住,您的业务可能在使用.NET Reflector时遇到问题。

+0

是的,我想我应该提到这不是一个选项,但反射器将是我们如何确定泄漏。由于种种原因,编写我自己的版本在这里不起作用。 – Dugan 2010-03-26 01:06:57

+0

甚至没有“直到供应商交付”解决方法? – jcolebrand 2010-03-26 02:11:50

+0

基本上,问题在于我们在何处部署,生产服务器已经有我们将要使用的组件的一个实例,并且我们无法触及那个(因为它在生产中)。这是一个内部问题,可能会在我们到达之前得到解决,但我很好奇在此期间如何处理这个问题。 – Dugan 2010-03-26 02:28:26

1

我们不得不使用第三方库(用Java开发)服务,并且我们认为,是这个库的内存泄漏。我们决定处理这个问题的简单方法是将服务分成两个不同的模块,一个是服务本身,另一个是业务代码,另一个是可执行文件。所以服务循环,调用另一个可执行文件,它运行在它自己的内存空间中,然后完成它的执行,永远不会因为内存泄漏而影响服务应用程序。

所以我的建议是将你的程序从错误的DLL中分离出来,或者缩短你使用它的时间,或者改变系统的体系结构,这样你就不会直接从“长时间运行”应用。

0

如果这是一个严重的问题,请将程序集加载到单独的AppDomain中,并孤立地创建您的躲闪类的实例。它还提供了一个很好的安全边界。

如果有静态成员保存在变量上,那么对于当前的appdomain中的泄漏没有任何可以做的,因此使用另一个是提供组件隔离的好方法。

将程序集加载到IAppDomain中后,它不能被卸载,但整个AppDomain可以被拆除,GC将收集它。