Ho un'applicazione che presenta una perdita di memoria lenta dalla parola "go".Come posso trovare il motivo per una coda di finalizzatore bloccata?
Utilizzo di Profiler di memoria ANTS Vedo che tutta la memoria trapelata è trattenuta dalla radice GC della coda del finalizzatore.
Sospetto che ciò che potrebbe essere accaduto è che il finalizzatore è bloccato in attesa di una serratura per essere disponibile.
Nessuno dei nostri corsi implementa i finalizzatori espliciti, li evitiamo di solito, questo mi fa pensare che il blocco potrebbe essere correlato a un sistema o una classe di libreria.
Ho usato SOS.dll
per dare un'occhiata al contenuto della coda del finalizzatore e se sto interpretando correttamente, allora riporta il primo elemento come un'istanza System.Threading.Thread
Tuttavia non sono sicuro se il capo della coda rappresenti effettivamente l'oggetto attualmente disposto o l'oggetto successivo da smaltire.
- Ci sono trucchi che posso utilizzare per scoprire cosa viene finalizzato?
- C'è un modo per scoprire su quale blocco è attivo il thread del finalizzatore?
- È possibile attivare eventuali debug aggiuntivi per tracciare le azioni del thread di finalizzazione?
- Cos'altro posso guardare?
Aggiornamento
stack del thread finalizzatori appare come segue:
ntdll.dll!_ZwWaitForSingle[email protected]() + 0x15 bytes
[email protected]() + 0x15 bytes
[email protected]() + 0x15 bytes
[email protected]() + 0x43 bytes
[email protected]() + 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
[email protected]@4() + 0xe bytes
rpcrt4.dll!_NdrClientCall2() + 0x144 bytes
[email protected]() + 0x7a bytes
[email protected]() + 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
[email protected]@12() + 0x12 bytes
[email protected]() + 0x27 bytes
[email protected]() + 0x1b bytes
Perché stai evitando i finalizzatori di norma? L'implementazione corretta del modello monouso * richiede * finalizzatore. – svick
@svick - Una nota su MSDN re. implementare IDisposable dice "Lascia fuori completamente il finalizzatore se una classe non possiede risorse non gestite" – chillitom
@svick - chillitom è corretto. Citando [Framework Design Guidelines] (http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613): "Davvero non vuoi scrivere un finalizzatore se puoi aiutarlo." – TrueWill