2010-07-25 144 views
0

我有一个通过COM组件(使用vb6创建)的包装管理应用程序(.net),其中Com组件也使用本机C++ dll。托管+非托管应用程序导致内存泄漏

应用程序作为后台进程运行,应该连续运行24 X 7. 应用程序在特定时间内运行正常,但在一段时间后崩溃。 可能的原因可能是C++ dll或com组件中的漏洞。有很多COM和C++ dll的代码。

因为我不熟悉COM和C++,我试图从托管应用程序解决问题。我正在考虑解决这个问题:如果托管应用程序开始消耗大量内存,那么我将重新启动托管应用程序。

1)如何以编程方式监视应用程序使用的总内存(managed + unmanaged)。

2)重新启动托管应用程序还释放非托管资源。

3)有没有其他的替代方法。

4)什么是最好的调试工具,用于监控也使用非托管资源的托管应用程序。

如果我不清楚我的解释,然后再问我一次。

任何帮助将不胜感激。

回答

1

我们如何以编程方式监视应用程序使用的总内存(managed + unmanaged)。

使用性能计数器。在开发/测试中最容易使用PerfMon在后台收集数据(使用数据收集集),然后在Excel或类似的分析结果。

如果您需要在生产用法中继续此操作,应用程序可以自己读取性能计数器(使用System.Diagnostics.PerformanceCounter和相关类)。

2)重新启动托管应用程序还释放非托管资源。

是的。

3)有没有其他的替代方法。

是:解决问题。

如果COM组件或C++库真泄漏然后那些真正需要是固定的(并且如果先前仅用于短寿命过程中的泄漏可能已经存在了很长一段时间)。

你可能会击中.NET的相互作用托管堆和GC与使用本机堆。托管GC在存在内存压力时运行(即,否则需要获得更多内存才能完成分配)。如果托管包装器不分配内存(或不多),则没有理由运行GC。当您从中引用COM组件时。NET引用保存在本机封装类型中,当封装器由GC收集时,此封装器释放COM实例(通过释放最后一次计数的COM引用)。

所以如果GC不运行,那么COM组件将不会被释放。它只需要COM实例使用大量的内存,并且总的进程内存提交可以开始增长。

有三种方法(按递减的偏好):

  1. 使用方法上的COM的实例,以释放其存储器使用(例如释放的子对象),如果它有一个。
  2. 当托管代码与它们结束时,显式释放COM组件实例—不等待使用Marshal.ReleaseComObject的GC —。
  3. 强制GC。

#3是最简单的,可以通过在运行几个小时后(例如在一个定时器上)强制完整的GC并查看内存使用性能计数器来确认此方法。如果是这种情况,请继续执行#1或#2。 (这实质上是我的第一个.NET项目之一发生的事情,大量未管理的堆的交互不会由于受管理的内存压力不足而未收集的管理实例释放。这种情况是为关键COM组件添加一个附加方法来释放它所持有的对象。)

相关问题