2009-05-12 3 views
7

Abbiamo attraversato una grande analisi della perdita di memoria e abbiamo trovato uno dei fattori che hanno contribuito alla mancata rimozione dei delegati sugli eventi causando che gli oggetti non siano sottoposti a GC abbastanza velocemente (o qualche volta per sempre).Qualsiasi idea su come scrivere una regola di analisi statica (FXCop) per assicurare che i delegati dell'evento vengano rimossi

Qualcuno ha qualche idea su come scrivere una regola in FXCop per assicurarsi che i delegati siano rimossi dai gestori?

Ho appena visto this e come tale chiederò lì per ulteriori informazioni.

risposta

2

Ok, accanto al problema di attuare il controllo effettivo (a mio parere questo è molto simile a un path coverage e quindi non pratico) - qui è il modo di scrivere una nuova FxCop regola è:

In un primo momento un po ' articoli che mi hanno aiutato una volta:

L'implementazione di una regola semplice non è un grosso problema. Nel progetto è necessario un file Rules.xml come risorsa incorporata (vedere here).Si deriva la classe da BaseIntrospectionRule e aggiungere il codice per il Check() - Metodo:

public override ProblemCollection Check(TypeNode typeNode) 
{ 
    if(type.IsPublic) 
    { 
    Problems.Add(new Problem(...)); 
    } 
    return Problems; 
} 

ho fatto qualche tempo fa. Spero che funzioni ancora come descritto :)

+0

grazie questo è il più vicino alla risposta che stavo cercando. Ma in tutta onestà anche le altre risposte sono vere, e stiamo implementando riferimenti deboli laddove possibile. –

0

È sicuro assumere che gli oggetti che implementano i gestori abbiano in qualche modo riferimenti all'oggetto con gli eventi? Se è così, è meglio capire come rompere il ciclo in un altro modo.

Abbiamo avuto qualcosa di simile in passato con i gestori di eventi nelle pagine ASP.NET. Anche gli oggetti che implementavano i gestori avevano riferimenti alle pagine. Dopo aver interrotto il maggior numero di collegamenti architettonicamente possibile, i pochi avanzi sono stati modificati in WeakReferences. Niente più problemi di memoria!

+0

Interessante ... grazie. –

3

Devi essere più specifico. Non è necessario verificare che TUTTI i delegati dell'evento siano stati annullati, perché in un caso comune un abbonato vive più breve di un editore. E una perdita di memoria si verifica solo quando il tuo abbonato sembra essere più longevo di un editore, quindi c'è un riferimento, che impedisce a GC di raccogliere l'oggetto editore.

Ora dobbiamo verificare che, se ti iscrivi a un evento su un oggetto a vita relativamente breve, puoi cancellarti da esso.

Un'euristica che riesco a fare in questo caso: analizzare tutti gli oggetti a variabile locale (definiti dal blocco di codice corrente {}) e tutti gli oggetti, che vengono eliminati in modo esplicito. Per ogni evento su questi oggetti conta il numero di volte in cui ti sei iscritto e il numero di volte in cui ti sei cancellato. Se il primo numero è maggiore, emettere un avviso.

Ovviamente questo non copre tutti i casi, ma suppongo che nessun approccio statico possa coprire tutti i casi in questo problema, è necessario un metodo che sia abbastanza buono.

Non menzionerò qui i vantaggi dell'analisi dinamica e delle revisioni del codice poiché si tratta di un argomento separato, non correlato alla domanda.

+0

Grazie. Apprezzo la risposta dettagliata. Sono abbastanza fiducioso sulle cose che voglio controllare. Quello che mi piacerebbe scoprire sono le informazioni su come effettivamente farlo in una regola FX. Non riesco a trovare informazioni decenti su come utilizzare gli assiemi FX per scrivere nuove regole complesse. –

1

È possibile imporre una regola per la gestione di tutte le sottoscrizioni di eventi tramite WeakReferences? Penso che questo dovrebbe essere più facile da implementare che dover analizzare il flusso reale del tuo programma.

Problemi correlati