我有一个应用程序从 go 开始就经历了缓慢的内存泄漏。
Using ANTS 内存分析器我可以看到所有泄漏的内存都由终结器队列的 GC 根保存。
我怀疑可能发生的情况是终结器死锁,等待锁变得可用。
我们的类都没有实现显式终结器,我们通常避免使用它们,这让我认为锁可能与系统或库类相关。
我用过SOS.dll
查看终结器队列的内容,如果我正确解释它,那么它会报告第一个项目是一个实例System.Threading.Thread
但是我不确定队列的头部是否实际上代表当前正在处理的对象或下一个要处理的对象。
- 我可以使用什么技巧来了解正在完成的内容吗?
- 有没有办法可以找出终结器线程正在等待什么锁?
- 是否可以打开任何额外的调试来跟踪终结器线程的操作?
- 我还能看什么?
Update
终结器线程的堆栈如下所示:
ntdll.dll!_ZwWaitForSingleObject@12() + 0x15 bytes
ntdll.dll!_ZwWaitForSingleObject@12() + 0x15 bytes
user32.dll!_NtUserPostMessage@16() + 0x15 bytes
kernel32.dll!_WaitForSingleObjectExImplementation@12() + 0x43 bytes
kernel32.dll!_WaitForSingleObject@8() + 0x12 bytes
ole32.dll!GetToSTA() + 0x72 bytes
ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall() - 0x1939 bytes
ole32.dll!CRpcChannelBuffer::SendReceive2() + 0xa6 bytes
ole32.dll!CAptRpcChnl::SendReceive() + 0x5b7 bytes
ole32.dll!CCtxComChnl::SendReceive() - 0x14b97 bytes
ole32.dll!NdrExtpProxySendReceive() + 0x43 bytes
rpcrt4.dll!@NdrpProxySendReceive@4() + 0xe bytes
rpcrt4.dll!_NdrClientCall2() + 0x144 bytes
ole32.dll!_ObjectStublessClient@8() + 0x7a bytes
ole32.dll!_ObjectStubless@0() + 0xf bytes
ole32.dll!CObjectContext::InternalContextCallback() - 0x511f bytes
ole32.dll!CObjectContext::ContextCallback() + 0x8f bytes
clr.dll!CtxEntry::EnterContext() + 0x119 bytes
clr.dll!RCWCleanupList::ReleaseRCWListInCorrectCtx() + 0x2bb bytes
clr.dll!RCWCleanupList::CleanupAllWrappers() - 0x20fb0 bytes
clr.dll!SyncBlockCache::CleanupSyncBlocks() + 0x1ec6 bytes
clr.dll!Thread::DoExtraWorkForFinalizer() + 0x411b5 bytes
clr.dll!WKS::GCHeap::FinalizerThreadWorker() + 0x8b bytes
clr.dll!Thread::DoExtraWorkForFinalizer() + 0xb6e76 bytes
clr.dll!Thread::ShouldChangeAbortToUnload() - 0x5f8 bytes
clr.dll!Thread::ShouldChangeAbortToUnload() - 0x53d bytes
clr.dll!ManagedThreadBase_NoADTransition() + 0x35 bytes
clr.dll!ManagedThreadBase::FinalizerBase() + 0xf bytes
clr.dll!WKS::GCHeap::FinalizerThreadStart() + 0xfb bytes
clr.dll!Thread::intermediateThreadProc() + 0x48 bytes
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
在我看来,您的 COM 服务器有问题。调用堆栈显示它正在尝试对单线程 COM 对象进行 IUnknown::Release() 调用。 ReleaseRCWListInCorrectCtx() 调用将其关闭,_NtUserPostMessage@16() 是将请求编组到拥有 COM 对象的 STA 的调用。
典型的原因是创建 COM 对象而不是泵送消息循环。对 STA 线程的硬性要求。您可以通过在主 UI 线程上创建它们并且从不阻塞它来避免这种情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)