我正在尝试使用 ANTS 探查器追踪应用程序中的内存泄漏。我追踪到垃圾收集器,其中有一个 System.Transactions.SafeIUnknown 对象列表,这些对象永远位于垃圾收集器中,位于终结器队列中,但从未被释放。
我在 System.Transactions.SafeIUnknown 上找不到任何文档,也无法确定什么会创建或引用它,这不是我们故意的。
我希望有人对此有一些了解。这是 20 字节的小泄漏,但是当我们的应用程序连续运行数天时,泄漏就会累积,我们有数百万个等待最终确定的数据,它开始消耗大量的内存。
有人有什么想法从这里去哪里吗?
跟进
我已将其追踪到正在使用的特定库。在我们通过这个特定的库执行任何 SQL 语句后,它似乎被抛在了后面。这些语句没有包装在事务中,但它们是通过一个相当复杂的循环来执行的,该循环具有泛型类型,目前看起来像是双三重间接,委托被传递用于运动并包装在闭包中,而闭包可以包装在更多闭包中。
我将继续尝试准确地束缚它,我的第一个停靠点是尝试看看是否可以使用类似的机制重现它。
SafeIUnknown 源自 SafeHandle。这是实现终结器的类。它很特别,它的终结代码运行在关键执行区(CER)中。这种代码提供了执行保证,异常被抑制。终结器运行 SafeIUnknown.ReleaseHandle(),它调用 Marshal.Release() 以释放由 SafeIUnknown 包装的 COM 接口指针。
在终结队列中看到大量此类包装器表明 Marshal.Release() 调用正在引发异常。防止包装器最终确定。找出它抛出异常的确切原因将是很棘手的。这是非托管代码轰炸,您几乎没有任何提示可以找出原因。 95% 的情况是堆损坏,这是一个非常难以解决的问题。最重要的是,因为这可能不是您的代码并且您没有任何来源。
您应该能够在良好的非托管代码调试器(如 WinDbug)中在第一次出现异常时获得断点。获取调试符号对于理解堆栈跟踪至关重要。然而,这可能仍然是一个遥远的目标。考虑从 Microsoft 支持获取帮助。或者像重建机器之类的重大事情。祝你好运!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)