Anatomia unui „scurgere de memorie“

voturi
159

În perspectivă .NET:

  • Ce este o scurgere de memorie ?
  • Cum se poate determina dacă scurgerile de aplicație? Care sunt efectele?
  • Cum se poate preveni o scurgere de memorie?
  • Dacă cererea dumneavoastră are scurgeri de memorie, se duce departe atunci când procesul iese sau este ucis? Sau pierderi de memorie în aplicația dumneavoastră afecta alte procese asupra sistemului chiar și după finalizarea procesului?
  • Și ce despre codul unmanaged accesate prin intermediul COM Interop și / sau P / Invoca?
Întrebat 01/08/2008 la 16:12
sursa de către utilizator
În alte limbi...                            


15 răspunsuri

voturi
106

Cea mai bună explicație l - am văzut este în capitolul 7 din libere Fundațiilor de programare e-book .

Practic, în NET o scurgere de memorie se produce atunci când obiectele referite sunt înrădăcinate și astfel nu pot fi gunoi colectate. Acest lucru se întâmplă accidental , atunci când țineți pe referințe dincolo de domeniul de aplicare intenționat.

Vei ști că ai scurgeri atunci când începe obtinerea OutOfMemoryExceptions sau utilizarea memoriei merge până dincolo de ceea ce te - ai aștepta ( PerfMon are frumos contoare de memorie).

Înțelegerea .NET Modelul de memorie „s este modul cel mai bun de a evita - l. Mai exact, înțelegerea modului în care funcționează colectorul de gunoi și modul în care referințele lucru - din nou, mă refer la capitolul 7 din e-book. De asemenea, să fie conștient de capcane comune, probabil, cele mai frecvente evenimente fiind. Dacă obiectul A este înregistrat la un eveniment obiect B , atunci obiecta O va lipi în jurul valorii de până la obiect B dispare , deoarece B deține o trimitere la A . Solutia este de a anula înregistrarea evenimentelor dvs. atunci când ați terminat.

Desigur, un profil bun de memorie va permite să vedeți graficele dvs. obiect și de a explora cuiburi / referirii obiectelor dvs. pentru a vedea în cazul în care referințele provin și ce obiect rădăcină este responsabil ( profil roșu-gate furnici , JetBrains dotMemory, memprofiler sunt foarte bune alegeri, sau puteți utiliza numai text windbg și SOS , dar mi - ar recomanda cu fermitate un produs comercial / vizual daca nu esti un guru real).

Eu cred că codul unmanaged este supus scurgeri sale tipice de memorie, cu excepția faptului că referințele comune sunt gestionate de către colectorul de gunoi. Aș putea fi greșit cu privire la acest ultim punct.

Publicat 01/08/2008 la 16:28
sursa de către utilizator

voturi
32

Strict vorbind, o scurgere de memorie este consumatoare de memorie care este „nu mai este folosit“ de program.

„Nu mai folosit“ are mai mult de un sens, aceasta ar putea însemna „nu mai referire la ea“, adică, total irecuperabil, sau ar putea însemna, de referință, recuperabile, neutilizate dar programul păstrează referințele oricum. Numai mai târziu se aplică .Net pentru obiecte perfect gestionate . Cu toate acestea, nu toate clasele sunt perfecte și la un moment dat o implementare negestionată de bază ar putea scurge în permanență resurse pentru acest proces.

În toate cazurile, cererea consumă mai multă memorie decât este strict necesar. Efectele părți, în funcție de ammount scurgeri, ar putea merge de la nici unul, la încetinirea cauzată de colectare excesivă, la o serie de excepții de memorie și în cele din urmă o eroare fatală, urmată de întreruperea procesului forțat.

Știi că o aplicație are o problemă legată de memorie atunci când monitorizarea indică faptul că mai mult și mai multă memorie este alocată procesului de după fiecare ciclu de colectare a gunoiului . În acest caz, sunt fie păstrarea prea mult în memorie, sau unele de punere în aplicare care stau la baza negestionate se scurge.

Pentru cele mai multe scurgeri de informații, resursele sunt recuperate atunci când procesul se încheie, însă unele resurse nu sunt recuperate întotdeauna, în unele cazuri precise, GDI mânere de cursor sunt notorii pentru asta. Desigur, dacă aveți un mecanism de comunicare interproces, memorie alocată în celălalt proces nu ar fi eliberat până când acest proces îl eliberează sau se termină.

Publicat 01/08/2008 la 18:52
sursa de către utilizator

voturi
28

Cred că „ceea ce este o scurgere de memorie“ și „care sunt efectele“ întrebări au fost răspuns bine deja, dar am vrut să mai adaug câteva lucruri pe celelalte întrebări ...

Cum de a înțelege dacă scurgerile aplicației

O modalitate interesantă este de a deschide perfmon și se adaugă urme de # octeți în toate grămezi și # colecții Gen 2 , în fiecare caz în căutarea doar la procesul. În cazul în care exercită o anumită caracteristică determină numărul total de bytes pentru a crește, iar memoria rămâne alocată după următoarea colectare Gen 2, s-ar putea spune că caracteristica pierderi de memorie.

Cum de a preveni

Alte avize bune au fost date. Aș adăuga doar că , probabil, cel mai frecvent trecute cu vederea cauza de pierderi de memorie NET este de a adăuga manipulare eveniment la obiecte , fără a scoate - le. Un eveniment atașat la handler un obiect este o formă de referință la acel obiect, astfel încât să prevină colectarea chiar și după ce toate celelalte referințe au plecat. Întotdeauna amintiți - vă să detașeze manipulare eveniment (folosind -=sintaxa în C #).

Are scurgerea merge departe atunci când ieșirile de proces, și ceea ce despre Interop COM?

Atunci când ieșirile de proces, toate de memorie mapate în spațiul de adrese este recuperată de către sistemul de operare, inclusiv orice obiecte COM servit de la DLL-uri. Comparativ rar, COM obiecte pot fi servite la procese separate. În acest caz, atunci când procesul iese, ar putea fi în continuare responsabil pentru memorie alocată în orice procese de server COM pe care le-ați utilizat.

Publicat 15/08/2008 la 17:11
sursa de către utilizator

voturi
18

Dacă aveți nevoie pentru a diagnostica o scurgere de memorie în .NET, verifica aceste link-uri:

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

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

Aceste articole descriu modul de a crea o imagine de memorie a procesului și cum să-l analizeze, astfel încât să puteți determina mai întâi dacă scurgerea este unmanaged sau gestionate, iar în cazul în care este gestionat, cum să dau seama unde vine de la.

Microsoft are, de asemenea, un instrument mai nou pentru a ajuta cu generatoare gropilor de accident, pentru a înlocui ADPlus, numit DebugDiag.

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

Publicat 15/08/2008 la 00:16
sursa de către utilizator

voturi
18

Aș defini pierderi de memorie ca un obiect nu eliberând toată memoria alocată, după ce a finalizat. Am găsit acest lucru se poate întâmpla în cererea dumneavoastră dacă utilizați Windows API și COM (de exemplu, codul unmanaged, care are un bug în ea sau nu este gestionat în mod corect), în cadrul și în componente terță parte. De asemenea, am constatat că nu tiding după folosirea unor obiecte cum ar fi stilouri poate provoca problema.

Eu personal am suferit Din excepții de memorie , care pot fi cauzate , dar nu sunt exclusiv pierderi de memorie în aplicații dot net. (MOF poate veni , de asemenea , de la pinning vezi Fixarea Artical ). Dacă nu primiți erori Oom sau trebuie să confirme dacă acesta este o scurgere de memorie , determinându - l atunci singura cale este de a profilului aplicației.

De asemenea, aș încerca și să asigure următoarele:

a) Tot ceea ce pune în aplicare IDisposable este dispus, fie cu ajutorul unui bloc în cele din urmă sau folosind declarația acestea includ perii, stilouri etc. (unii oameni susțin pentru a seta totul pentru nimic în plus)

b) Orice lucru care are o metodă de închidere este închis din nou, folosind în cele din urmă sau declarația folosind (deși am găsit folosind nu întotdeauna aproape în funcție dacă ați declarat obiectul în afara folosind declarația)

c) Dacă utilizați codul unmanaged / Windows API că acestea sunt tratate corect după. (Unele au curat metode pentru a elibera resurse)

Sper că acest lucru vă ajută.

Publicat 01/08/2008 la 18:57
sursa de către utilizator

voturi
15

Utilizarea CRJ Profiler de la Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en este o modalitate foarte bună de a determina de memorie care obiectele sunt exploatație, ceea ce conduce de execuție de curgere la crearea acestor obiecte, precum și , de asemenea , monitorizarea care obiectele vii în cazul în care pe heap (fragmentare, LOH, etc.).

Publicat 16/08/2008 la 20:54
sursa de către utilizator

voturi
14

Cea mai bună explicație a modului în care funcționează colectorul de gunoi este în Jeff Richters CLR prin intermediul C # carte, (Ch. 20). Citind acest lucru dă o mare pregătire pentru înțelegerea modului în care persistă obiecte.

Una dintre cele mai comune cauze de înrădăcinare obiectelor accidental este cupland evenimente outisde o clasă. Dacă cârlig un eveniment extern

de exemplu

SomeExternalClass.Changed += new EventHandler(HandleIt);

și să uitați să desprindeți să-l când eliminați, apoi SomeExternalClass are un ref la clasa ta.

După cum sa menționat mai sus, profiler -ul de memorie SciTech este excelent la care vă arată rădăcinile de obiecte pe care bănuiți că prezintă scurgeri.

Dar există, de asemenea, o modalitate foarte rapidă de a verifica un anumit tip este de a folosi doar WnDBG (puteți utiliza chiar și acest lucru în fereastra imediat VS.NET în timp ce atașat):

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

Acum , face ceva care credeți că va dispune obiectele de acest tip ( de exemplu , închide o fereastră). Este util aici pentru a avea un buton undeva de depanare , care va rula System.GC.Collect()de câteva ori.

Apoi , executați !dumpheap -stat -type <TypeName>din nou. În cazul în care numărul nu a mers în jos, sau nu a mers în jos la fel de mult cum vă așteptați, atunci aveți o bază pentru investigații suplimentare. (Am primit acest sfat de la un seminar dat de Ingo Rammer ).

Publicat 27/08/2008 la 15:12
sursa de către utilizator

voturi
14

Cred că într-un mediu gestionat, o scurgere ar fi te ține o referință inutilă o bucată mare de memorie în jurul valorii.

Publicat 01/08/2008 la 16:19
sursa de către utilizator

voturi
10

De ce oamenii cred că o scurgere de memorie în .NET nu este la fel ca orice altă scurgere?

O scurgere de memorie este atunci când atașați la o resursă și nu lăsa să plece. Puteți face acest lucru, atât în ​​gestionate și în codificare negestionat.

În ceea ce privește .NET, precum și alte instrumente de programare, au existat idei despre colectarea gunoiului, și alte modalități de a minimiza situații care vor face scurgeri de cerere. Dar cea mai bună metodă de prevenire a scurgerilor de memorie este că aveți nevoie pentru a înțelege modelul de memorie de bază, și modul în care funcționează lucrurile, pe platforma pe care îl utilizați.

Crezând că GC și alte magie va curăța mizeria este scurt mod de pierderi de memorie, și va fi dificil de a găsi mai târziu.

Când codificare negestionate, în mod normal, asigurați-vă că pentru a curăța, știi că resursele pe care le Apucati, va fi responsabilitatea dumneavoastră pentru a curăța, nu omului de serviciu.

În .NET, pe de altă parte, o mulțime de oameni cred că GC va curăța totul. Ei bine, face unele pentru tine, dar trebuie să vă asigurați că este așa. .NET se înfășurați o mulțime de lucruri, astfel încât să nu știi întotdeauna dacă aveți de-a face cu o resursă gestionate sau negestionate, și trebuie să vă asigurați ceea ce face. fonturi de manipulare, resurse GDI, director activ, baze de date etc este de obicei lucruri pe care trebuie să se uite pentru.

În termeni gestionate voi pune gâtul meu pe linie să spun că dispare odată ce procesul este ucis / eliminat.

Văd o mulțime de oameni au acest lucru, deși, și eu chiar sper acest lucru se va termina. Nu puteți cere utilizatorului să termine aplicația pentru a curăța mizeria! Uitați-vă la un browser, care poate fi IE, FF, etc, apoi deschideți, să zicem, Google Reader, se lasa sa stea timp de câteva zile, și uita-te la ceea ce se întâmplă.

Dacă apoi deschideți o altă filă în browser-ul, surf la unele site-ul, apoi închideți fila care a găzduit cealaltă pagină care a făcut scurgerea de browser, crezi că browser-ul va elibera memoria? Nu atât cu IE. Pe computerul meu IE va mânca cu ușurință 1 GiB de memorie într-un interval scurt de timp (aproximativ 3-4 zile) în cazul în care folosesc Google Reader. Unele newspages sunt chiar mai rău.

Publicat 01/09/2008 la 13:19
sursa de către utilizator

voturi
10

Cred că într-un mediu gestionat, o scurgere ar fi te ține o referință inutilă o bucată mare de memorie în jurul valorii.

Absolut. De asemenea, nu folosind metoda .Dispose () pe obiecte de unică folosință, atunci când este cazul poate provoca scurgeri mem. Cel mai simplu mod de a face acest lucru este cu un bloc folosind, deoarece se execută în mod automat .Dispose () la sfârșitul anului:

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

Și dacă creați o clasă care utilizează obiecte neamenajate, dacă nu sunteți de punere în aplicare în mod corect IDisposable, ai putea fi cauza pierderi de memorie pentru utilizatorii de clasa lui.

Publicat 05/08/2008 la 23:47
sursa de către utilizator

voturi
9

Toate scurgerile de memorie sunt rezolvate de încetare a programului.

Scurgeri suficientă memorie și sistemul de operare poate decide să rezolve problema în numele dumneavoastră.

Publicat 04/08/2008 la 15:09
sursa de către utilizator

voturi
9

Voi de acord cu Bernard în .net ce o scurgere de mem ar fi.

Ai putea profilul aplicației pentru a vedea utilizarea de memorie, și de a determina că, în cazul său gestionarea o mulțime de memorie atunci când nu ar trebui să fie ai putea spune că are o scurgere.

În termeni gestionate voi pune gâtul meu pe linie să spun că dispare odată ce procesul este ucis / eliminat.

Codul unmanaged este propria fiară și dacă există o scurgere în cadrul acesteia, va urma un standard de mem. scurgere definiție.

Publicat 01/08/2008 la 16:23
sursa de către utilizator

voturi
7

De asemenea, ține cont de faptul că .NET are două grămezi, una fiind mare grămada de obiect. Eu cred ca obiecte de aproximativ 85k sau mai mari sunt puse pe movila. Aceasta are o grămadă reguli diferite de viață decât grămada regulate.

Dacă creați structuri de memorie de mari dimensiuni (dicționar sau al lui List) ar prudent să meargă lookup care sunt regulile exacte.

În ceea ce privește recuperarea memoriei la încetarea procesului, cu excepția cazului în care rulează Win98 sau echivalent, totul este eliberat înapoi la sistemul de operare la terminare. Singurele excepții sunt lucruri care sunt deschise cross-proces și un alt proces are încă resursa deschisă.

COM Obiectele pot fi Tho dificil. Dacă utilizați întotdeauna IDisposemodelul, vei fi în siguranță. Dar am dat peste câteva ansambluri Interop care implementează IDispose. Cheia aici este de a apela Marshal.ReleaseCOMObjectatunci când ați terminat cu ea. COM Obiectele folosesc în continuare standardul de numărare de referință COM.

Publicat 07/08/2008 la 14:17
sursa de către utilizator

voturi
6

Am găsit .Net memorie Profiler un ajutor foarte bun atunci când a găsi scurgeri de memorie în .Net. Nu e liber ca Microsoft CLR Profiler, dar este mai rapid și mai mult , până la punctul în opinia mea. A

Publicat 20/08/2008 la 19:39
sursa de către utilizator

voturi
1

O definiție este: Nu se poate elibera de memorie imposibil de găsit, care nu mai pot fi alocate nou proces în timpul execuției procesului de alocare. Acesta poate fi în mare parte vindecate prin utilizarea unor tehnici GC sau detectate prin instrumente automate.

Pentru mai multe informații, vă rugăm să vizitați http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .

Publicat 27/08/2014 la 16:22
sursa de către utilizator

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