0

A legacy c++ applications with sometimes notorious memory leak issues has to be called from a .Net server based windows application. .Net garbage collection times are not determinable and sometime the c++ object are destroyed or not destroyed "on time" producing unpredictable results and generally crashing the c# web app. What is the best way to push the c++ objects onto the garbage collection stack as frequently as possible, but not so often as to remove the .Net reference to the COM object. Keep in mind that the COM objects can spawn sub-objects so the .Net reference count of the COM objects can change with just a function call and not necessarily an instantiation.

As the memory leaks occur and the COM objects are not cleaned up, performance degrades until it is so slow that IIS trips on itself a few times and then crashes. Restarting IIS fixes the issue until the next time. Periodic restarts help, but a busy day can cause this during the business day.

I had to resolve this using .Net 1.1 a couple of years ago. Wondering if someone else had my solution or a better one. This is NOT ASP.NET. It is a .Net dll.

The final result was not completely satisfactory and the web server crashes every few months.

4

2 回答 2

1

您问“尽可能频繁地将 c++ 对象推送到垃圾收集堆栈的最佳方法是什么”,但 c++ 对象永远不会被垃圾收集。也许这样看...

您有一个实例化一堆 c++ 对象的进程。其中一些 c++ 对象实现了 COM 对象,因此它们的生命周期通过 AddRef/Release 进行管理。其中一些 COM 对象被导入 .NET 世界,并使用 RCW(运行时可调用包装器)进行包装。只有 RCW 是 .NET 对象并进入垃圾收集堆。

在没有您的任何干预的情况下,RCW 最终将被 GC 处理,并且当这种情况发生时,它将针对其底层 COM 对象执行 Release。如果要立即释放 COM 对象,无需等待 GC,可以调用...

System.Runtime.InteropServices.Marshal.ReleaseComObject

...甚至 FinalReleaseComObject 如果您确定这是您想要的。

回到您的问题:您想知道如何在不释放 .NET 对 COM 对象的引用的情况下删除 c++ 对象。由于 .NET 堆中不存在 c++ 对象,因此无法直接实现这一点。您可以从您的 COM 对象中公开一个删除其所有 c++ 对象的方法,然后简单地从您的 .NET 代码中调用它。但我猜你的 COM 对象是否有可能识别出你已经在做的所有泄露的 c++ 对象。

希望我已经解释了为什么无法实现您在问题中的建议,但是有很多工具可以帮助您查找和修复内存泄漏。我建议使用 LeakDiag 之类的工具(在 StackOverflow 上搜索它)来找出你的 c++ 代码在哪里泄漏内存。

如果您使用的是 IIS6 或更高版本,实用的解决方案是配置应用程序池回收。您可以调整这些数字,以便在进程泄漏足够的内存造成问题之前杀死并重新启动进程,并且它通常以用户不会注意到任何停机时间的方式工作。

于 2009-02-26T12:41:35.573 回答
0

创建一个 COM+ 应用程序并将您使用的 COM 类放入该应用程序中。这样,所有 COM 对象都在一个单独的进程中实例化。您可以定期释放所有 COM 对象,然后重新启动 COM+ 应用程序进程。

于 2009-02-26T12:49:16.977 回答