我正在尝试使用ANTS探查器跟踪应用程序中的内存泄漏。我将它跟踪到垃圾收集器,在那里我们有一个对象列表System.Transactions.SafeIUnknown,它们永远位于垃圾收集器中,位于终结器队列中但从未被释放。
我无法找到System.Transactions.SafeIUnknown上的文档,也无法确定创建或引用它的内容,这对我们来说并不是故意的。
我希望有人可能对此有所了解。这是一个20字节的小漏洞,但是当我们的应用程序连续运行数天时,泄漏就会增加,我们有数百万这些等待最终确定,它开始耗费大量内存。
任何想法从哪里开始?
我已将其追踪到正在使用的特定库中。在我们通过这个特定的库执行任何SQL语句后,它似乎被遗忘了。 statemtements不包含在事务中,但它们是通过一个相当复杂的循环执行的,泛型类型和当前看起来像双三方间接的代理被传递给sport并包装在可以包装在更多闭包中的闭包中。 我将继续尝试将其完全绑定,我的第一个停靠点是尝试查看是否可以使用类似的机制重现它。
答案 0 :(得分:4)
SafeIUnknown派生自SafeHandle。这是实现终结器的类。它很特殊,它的终结代码在关键执行区(CER)中运行。这种代码提供了执行保证,异常被抑制。终结器运行SafeIUnknown.ReleaseHandle(),它调用Marshal.Release()来释放由SafeIUnknown包装的COM接口指针。
在终结队列中看到很多这些包装器表明Marshal.Release()调用正在抛出异常。防止包装器完成。找出它抛出异常的确切原因将是棘手的。这是非托管代码爆炸,你可以找到一些提示来找出原因。 95%的情况是堆损坏,这是一个非常难以解决的问题。最重要的是因为这可能不是你的代码,你没有任何来源。
你应该能够在第一次机会异常的好的非托管代码调试器(如WinDbug)中获得断点。获取调试符号对于理解堆栈跟踪至关重要。然而,它可能仍然是一个远景。请考虑从Microsoft支持获取帮助。或者像重建机器那样激烈的东西。祝你好运!
答案 1 :(得分:1)
SafeIUnknown源自System.Transactions中的一些方法,其中一个是TransactionScope
构造函数和Dispose方法。对这些调用最终会在名为Transaction
的{{1}}类的内部方法中进一步调用,该类进一步调用本机Ole32函数JitSafeGetContextTransaction
,该函数返回CoGetDefaultContext
的实例。
这暗示有问题的对象与事务上下文的内部表示有关。
可能是您没有正确释放交易或交易范围吗?如果是这样,您使用的数据提供商可能存在一些问题吗?