Anatomia di una "perdita di memoria"

voti
159

In prospettiva NET:

  • Che cosa è una perdita di memoria ?
  • Come è possibile determinare se le vostre perdite di applicazione? Quali sono gli effetti?
  • Come si può evitare che una perdita di memoria?
  • Se l'applicazione ha perdita di memoria, lo fa andare via quando il processo si chiude o viene ucciso? O se le perdite di memoria nell'applicazione influenzano altri processi del sistema anche dopo il completamento di processo?
  • E per quanto riguarda il codice non gestito si accede tramite l'interoperabilità COM e / o P / Invoke?
È pubblicato 01/08/2008 alle 16:12
fonte dall'utente
In altre lingue...                            


15 risposte

voti
106

La spiegazione migliore che ho visto è nel capitolo 7 della libera Fondamenti di programmazione e-book .

In sostanza, in NET una perdita di memoria si verifica quando gli oggetti di riferimento sono radicate e quindi non può essere garbage collection. Ciò si verifica accidentalmente quando si tiene a riferimenti al di là del campo di applicazione previsto.

Potrai sapere che avete perdite quando si avvia sempre OutOfMemoryExceptions o l'uso della memoria risale al di là di quanto ci si aspetterebbe ( PerfMon ha contatori di memoria piacevoli).

Capire .NET modello di memoria s' è il tuo modo migliore per evitare di esso. In particolare, capire come funziona il garbage collector e come riferimenti lavoro - ancora una volta, vi rimando al capitolo 7 del e-book. Inoltre, essere consapevoli di problemi comuni, probabilmente i essendo eventi più comuni. Se oggetto A è registrato ad un evento su un oggetto B , quindi opporsi A si attacca intorno fino all'oggetto B scompare perché B contiene un riferimento a A . La soluzione è quella di annullare la registrazione eventi quando hai finito.

Naturalmente, un buon profilo di memoria vi permetterà di vedere i tuoi oggetti grafici ed esplorare la nidificazione / riferimento degli oggetti per vedere dove i riferimenti sono provenienti da e che cosa oggetto radice è responsabile ( profilo formiche rosse-gate , JetBrains dotMemory, memprofiler sono veramente buoni scelte, oppure è possibile utilizzare il solo testo WinDbg e SOS , ma mi consiglia vivamente di un prodotto commerciale / visivo a meno che non sei un vero guru).

Credo che il codice non gestito è soggetto alle sue perdite di memoria tipici, salvo che i riferimenti condivisi sono gestite dal garbage collector. Potrei sbagliarmi su questo ultimo punto.

Risposto il 01/08/2008 a 16:28
fonte dall'utente

voti
32

A rigor di termini, una perdita di memoria sta consumando memoria che è "non più utilizzato" dal programma.

"Non è più usato" ha più di un significato, potrebbe significare "nessun altro riferimento ad essa", cioè totalmente irrecuperabile, o potrebbe significare, si fa riferimento, recuperabile, non utilizzata ma il programma mantiene i riferimenti in ogni caso. Solo più tardi si applica al NET per gli oggetti perfettamente gestiti . Tuttavia, non tutte le classi sono perfetti e ad un certo punto un'implementazione non gestito sottostante potrebbero perdere le risorse in modo permanente per quel processo.

In tutti i casi, l'applicazione consuma più memoria di quanto strettamente necessario. Gli effetti lati, a seconda del ammount trapelato, potrebbe andare da nessuno, al rallentamento causato dalla raccolta eccessiva, ad una serie di eccezioni di memoria e, infine, un errore fatale seguito da terminazione processo forzata.

Sai un'applicazione ha un problema di memoria quando il monitoraggio mostra che più e più memoria viene allocata per il processo dopo ogni ciclo di raccolta dei rifiuti . In tal caso, o si è tenendo troppo in memoria, o qualche sottostante implementazione non gestito perde.

Per la maggior parte delle perdite, le risorse vengono recuperati quando il processo viene terminato, tuttavia alcune risorse non sono sempre recuperati in alcuni casi precisi, maniglie cursore GDI sono noti per questo. Naturalmente, se si dispone di un meccanismo di comunicazione tra processi, memoria allocata nell'altro processo non sarebbe liberato fino a quel processo libera o termina.

Risposto il 01/08/2008 a 18:52
fonte dall'utente

voti
28

Credo che il "che cosa è una perdita di memoria" e "quali sono gli effetti" sono stati già risposto bene alle domande, ma ho voluto aggiungere un paio di cose sulle altre domande ...

Come capire se i vostri perdite di applicazione

Un modo interessante è quello di aprire perfmon e aggiungere tracce per # byte in tutti i cumuli e # Gen 2 collezioni , in ogni caso guardando proprio al vostro processo. Se si esercita una particolare caratteristica fa sì che i byte totali per aumentare, e che la memoria rimane assegnato dopo la successiva raccolta Gen 2, si potrebbe dire che la funzione perde la memoria.

Come prevenire

Altre buone opinioni sono state date. Vorrei solo aggiungere che forse il più comunemente trascurato causa di perdite di memoria NET è quello di aggiungere gestori di eventi agli oggetti senza rimuoverli. Un gestore di evento associato a un oggetto è una forma di riferimento a tale oggetto, in modo impedirà la raccolta, anche dopo tutti gli altri riferimenti sono andati. Ricordarsi sempre di separare i gestori di eventi (utilizzando la -=sintassi C #).

Ha la perdita andare via quando le uscite di processo, e per quanto riguarda l'interoperabilità COM?

Quando le vostre uscite di processo, tutta la memoria mappata nel suo spazio di indirizzamento viene recuperato dal sistema operativo, compresi eventuali oggetti COM servita dalle DLL. Comparativamente raramente, oggetti COM possono essere serviti da processi separati. In questo caso, quando il processo si chiude, si può essere ancora responsabile per la memoria allocata in tutti i processi di server COM che si è utilizzato.

Risposto il 15/08/2008 a 17:11
fonte dall'utente

voti
18

Se avete bisogno di diagnosticare una perdita di memoria in .NET, controllare questi link:

http://msdn.microsoft.com/en-us/magazine/cc163833.aspx

http://msdn.microsoft.com/en-us/magazine/cc164138.aspx

Tali articoli descrivono come creare un dump della memoria del vostro processo e come analizzare in modo che si può prima determinare se il vostro perdita è gestito o gestito, e se è riuscito, come per capire dove si proviene.

Microsoft ha anche uno strumento più recente per assistere con la generazione di crash dump, per sostituire ADPlus, chiamato DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

Risposto il 15/08/2008 a 00:16
fonte dall'utente

voti
18

Definirei perdite di memoria come un oggetto non liberare tutta la memoria assegnata dopo aver completato. Ho trovato questo può accadere nella vostra applicazione, se si utilizza Windows API e COM (cioè il codice non gestito che ha un bug in esso o non viene gestito correttamente), nel quadro e componenti di terze parti. Ho anche trovato non riassetto dopo l'utilizzo di determinati oggetti come penne può causare il problema.

Personalmente ho sofferto Fuori eccezioni di memoria che possono essere causati, ma non sono esclusivi di perdite di memoria nelle applicazioni dot net. (OOM può provenire anche da appuntare vedere Pinning Artical ). Se non si è trovato errori OOM o bisogno di confermare se si tratta di una perdita di memoria causando quindi l'unico modo è quello di profilo la vostra applicazione.

Vorrei anche cercare di garantire quanto segue:

a) Tutto ciò che implementa IDisposable è disposto sia usando un blocco finally o l'istruzione using questi includono spazzole, penne ecc (alcune persone sostengono di impostare tutto a nulla in aggiunta)

b) Tutto ciò che ha un metodo vicino è chiuso ancora una volta utilizzando finalmente o l'istruzione using (anche se ho trovato usando non sempre vicino a seconda se si dichiarato l'oggetto fuori l'istruzione using)

c) Se si utilizza il codice non gestito / API di Windows è che queste sono trattate correttamente dopo. (Alcuni hanno ripulire metodi per rilasciare le risorse)

Spero che questo ti aiuti.

Risposto il 01/08/2008 a 18:57
fonte dall'utente

voti
15

Utilizzando CLR Profiler da Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en è un ottimo modo per determinare quali oggetti sono in possesso di memoria, cavi flusso quello di esecuzione alla creazione di questi oggetti, e anche monitorare quali oggetti vivo dove sul mucchio (frammentazione, LOH, ecc).

Risposto il 16/08/2008 a 20:54
fonte dall'utente

voti
14

La migliore spiegazione di come funziona il garbage collector è Jeff Richters CLR via C # libro, (Ch. 20). La lettura di questo dà una grande messa a terra per capire come gli oggetti persistono.

Una delle cause più comuni di radicamento oggetti accidentalmente è di collegare gli eventi outisde una classe. Se si collega un evento esterno

per esempio

SomeExternalClass.Changed += new EventHandler(HandleIt);

e dimenticare di sganciare ad esso quando si smaltire, quindi SomeExternalClass ha un rif alla classe.

Come accennato in precedenza, la memoria di profiler SciTech è eccellente a che vi mostra le radici di oggetti si sospetta siano perdite.

Ma v'è anche un modo molto veloce per controllare un particolare tipo è semplicemente usare WnDBG (si può anche utilizzare questo nella finestra immediata VS.NET, mentre in allegato):

.loadby sos mscorwks
!dumpheap -stat -type <TypeName>

Ora fare qualcosa che pensi possano smaltire gli oggetti di quel tipo (ad esempio, chiudere una finestra). E 'utile qui per avere un pulsante di debug da qualche parte che verrà eseguito System.GC.Collect()un paio di volte.

Quindi eseguire !dumpheap -stat -type <TypeName>di nuovo. Se il numero non è andata giù, o non è andato giù il più ci si aspetta, allora hai una base per ulteriori indagini. (Ho ottenuto questo suggerimento da un seminario tenuto da Ingo Rammer ).

Risposto il 27/08/2008 a 15:12
fonte dall'utente

voti
14

Credo che in un ambiente gestito, una perdita sarebbe ti impedisce un riferimento necessario un grande pezzo della memoria intorno.

Risposto il 01/08/2008 a 16:19
fonte dall'utente

voti
10

Perché la gente pensa che una perdita di memoria in .NET non è la stessa di qualsiasi altra fuga di notizie?

Una perdita di memoria è quando si collega a una risorsa e non lasciarlo andare. È possibile farlo sia nel gestito e non gestito nella codifica.

Per quanto riguarda .NET, e altri strumenti di programmazione, ci sono state le idee circa la raccolta dei rifiuti, e altri modi di ridurre al minimo le situazioni che renderanno la vostra perdita di applicazione. Ma il metodo migliore per prevenire perdite di memoria è che è necessario capire il vostro modello di memoria di base, e come funziona cose, sulla piattaforma che si sta utilizzando.

Credendo che GC e altre magie saranno ripulire il pasticcio è la strada più breve per le perdite di memoria, e sarà difficile da trovare in seguito.

Quando si codifica non gestito, che normalmente assicurarsi di ripulire, si sa che le risorse si prende in mano, sarà la vostra responsabilità di ripulire, non il bidello del.

In .NET d'altra parte, un sacco di gente pensa che il GC ripulire tutto. Beh, lo fa anche per te, ma è necessario fare in modo che sia così. .NET viene disposto un sacco di cose, in modo che non sempre sa se si tratta di una risorsa gestita o non gestito, ed è necessario assicurarsi che cosa che cosa hai a che fare con. font movimentazione, le risorse GDI, active directory, database, ecc è in genere cose che avete bisogno di guardare fuori per.

In termini gestiti Porrò il mio collo sulla linea a dire lo fa andare via una volta che il processo viene ucciso / rimosso.

Vedo un sacco di persone hanno questo però, e spero davvero che questo finirà. Non si può chiedere all'utente di sospendere l'applicazione per ripulire il pasticcio! Date un'occhiata a un browser, che può essere IE, FF, ecc, quindi aprire, per esempio, Google Reader, lasciate stare per qualche giorno, e guardare a ciò che accade.

Se quindi si apre un'altra scheda nel browser, navigare in qualche sito, quindi chiudere la scheda che ha ospitato l'altra pagina che ha fatto la perdita del browser, pensi che il browser rilascerà la memoria? Non così con IE. Sul mio computer IE sarà facile mangiare 1 GB di memoria in un breve lasso di tempo (circa 3-4 giorni) se uso Google Reader. Alcuni newspages sono anche peggio.

Risposto il 01/09/2008 a 13:19
fonte dall'utente

voti
10

Credo che in un ambiente gestito, una perdita sarebbe ti impedisce un riferimento necessario un grande pezzo della memoria intorno.

Assolutamente. Inoltre, non utilizzando il metodo .Dispose () sugli oggetti monouso quando appropriato può causare perdite mem. Il modo più semplice per farlo è con un blocco utilizzando perché esegue automaticamente .Dispose () alla fine:

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

E se si crea una classe che utilizza oggetti non gestiti, se non stai corretta attuazione IDisposable, si potrebbe essere la causa perdite di memoria per gli utenti della vostra classe.

Risposto il 05/08/2008 a 23:47
fonte dall'utente

voti
9

Tutte le perdite di memoria vengono risolte dalla terminazione del programma.

Perdita di memoria sufficiente e il sistema operativo può decidere di risolvere il problema a vostro nome.

Risposto il 04/08/2008 a 15:09
fonte dall'utente

voti
9

Io concordo con Bernard come al .net quale sarebbe una perdita di mem.

Si potrebbe profilo l'applicazione per vedere il suo utilizzo di memoria, e determinare che se la sua gestione di una grande quantità di memoria quando non dovrebbe essere si potrebbe dire che ha una perdita.

In termini gestiti Porrò il mio collo sulla linea a dire lo fa andare via una volta che il processo viene ucciso / rimosso.

codice non gestito è la sua propria bestia e se una perdita esiste all'interno di esso, seguirà un mem standard. perdita di definizione.

Risposto il 01/08/2008 a 16:23
fonte dall'utente

voti
7

Anche tenere a mente che NET ha due cumuli, uno è grande mucchio oggetto. Credo oggetti di circa 85k o più grandi sono messi in questo mucchio. Questo mucchio ha un diverso regole vita che il cumulo regolare.

Se si sta creando strutture di memoria di grandi dimensioni (il Dizionario o la lista di) sarebbe prudente andare di ricerca quali sono le regole esatte sono.

Per quanto riguarda la bonifica della memoria al termine del processo, a meno che la vostra esecuzione Win98 o equivalenti, tutto viene rilasciato torna al sistema operativo al termine. Le uniche eccezioni sono le cose che vengono aperti cross-process e un altro processo ha ancora la risorsa aperta.

Oggetti COM possono essere tho difficile. Se si usa sempre il IDisposemodello, sarai al sicuro. Ma ho eseguito attraverso alcuni assembly di interoperabilità che implementano IDispose. La chiave qui è quello di chiamare Marshal.ReleaseCOMObjectquando hai finito con esso. Gli oggetti COM usano ancora il conteggio dei riferimenti COM standard.

Risposto il 07/08/2008 a 14:17
fonte dall'utente

voti
6

Ho trovato .Net Memory Profiler un ottimo aiuto quando trovare le perdite di memoria in .NET. Non è libero come la Microsoft CLR Profiler, ma è più veloce e più al punto, a mio parere. UN

Risposto il 20/08/2008 a 19:39
fonte dall'utente

voti
1

Una definizione è: impossibile liberare memoria irraggiungibile, che non può più essere assegnato a nuovo processo durante l'esecuzione del processo di assegnazione. Può essere curata principalmente utilizzando tecniche GC o identificato tramite strumenti automatizzati.

Per ulteriori informazioni, si prega di visitare il sito http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .

Risposto il 27/08/2014 a 16:22
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more