Anatomie van een "Memory Leak"

stemmen
159

In .NET perspectief:

  • Wat is een geheugenlek ?
  • Hoe kunt u bepalen of uw aanvraag lekken? Wat zijn de gevolgen?
  • Hoe kunt u een geheugenlek te voorkomen?
  • Als uw toepassing geheugenlek, is het weg te gaan wanneer het proces verlaat of wordt gedood? Of heeft geheugenlekken in de toepassing invloed op andere processen op het systeem, zelfs na proces voltooid?
  • En hoe zit het met unmanaged code toegankelijk via COM Interop en / of P / Roep?
De vraag is gesteld op 01/08/2008 om 16:12
bron van user
In andere talen...                            


15 antwoorden

stemmen
106

De beste verklaring die ik heb gezien is in hoofdstuk 7 van de vrije Foundations of Programming e-book .

In principe in NET een geheugenlek wanneer objecten waarnaar wordt verwezen worden verankerd en daardoor niet opgeschoond. Dit gebeurt per ongeluk als je vast te houden aan referenties buiten het beoogde toepassingsgebied.

Je weet dat je lekken als je het krijgen van OutOfMemoryExceptions starten of geheugengebruik omhoog gaat verder dan wat je zou verwachten ( PerfMon heeft mooie herinnering tellers).

Inzicht in .NET 's geheugen model is de beste manier om het te vermijden. In het bijzonder, te begrijpen hoe de garbage collector werkt en hoe referenties werken - nogmaals, verwijs ik u naar hoofdstuk 7 van het e-book. Ook is rekening te houden met valkuilen, waarschijnlijk de meest voorkomende zijn evenementen. Als object A wordt een event object B , dan object A zal blijven hangen tot voorwerp B verdwijnt omdat B verwijzing naar bevat A . De oplossing is om uw evenement uitschrijven als je klaar bent.

Natuurlijk zal een goed geheugen profiel laten u zien uw object grafieken en verken de nesten / referencing van uw objecten te zien waar referenties vandaan komen en wat hoofdobject verantwoordelijk is ( rood-poort mieren profiel , JetBrains dotMemory, memprofiler zijn echt goed keuzes, of u kunt de text-only te gebruiken WinDbg en SOS , maar ik zou raden een commercieel / visuele product, tenzij je een echte goeroe).

Ik geloof dat unmanaged code is onderworpen aan de typische geheugenlekken, met uitzondering van die gedeelde referenties worden beheerd door de garbage collector. Ik kan het mis hebben over dit laatste punt.

antwoordde op 01/08/2008 om 16:28
bron van user

stemmen
32

Strikt genomen, is een geheugenlek consumeren geheugen dat is "niet meer gebruikt" door het programma.

"Niet meer gebruikt" heeft meer dan één betekenis, kan dit betekenen "geen verwijzing meer aan de hand", dat wil zeggen volledig onherstelbaar, of het zou kunnen betekenen, waarnaar wordt verwezen, voor vergoeding in aanmerking, ongebruikt maar het programma blijft de referenties toch. Alleen de latere toepassing op .NET voor perfect beheerde objecten . Echter, niet alle klassen zijn perfect en op een gegeven moment een onderliggende unmanaged implementatie kon middelen permanent lekken voor dat proces.

In alle gevallen is de toepassing verbruikt meer geheugen dan strikt nodig is. De zijkanten effecten, afhankelijk van de ammount gelekt, zou kunnen gaan van niemand, tot vertraging veroorzaakt door overmatige collectie, om een ​​reeks van het geheugen uitzonderingen en uiteindelijk een fatale fout, gevolgd door geforceerde proces beëindiging.

Je weet dat het programma heeft een geheugen probleem wanneer uit de bewaking blijkt dat meer en meer geheugen aan uw proces wordt toegekend na elke garbage collection cyclus . In een dergelijk geval bent u ofwel het houden van te veel in het geheugen, of een onderliggende onbeheerde implementatie lekt.

Voor de meeste lekken, middelen worden hersteld wanneer het proces wordt beëindigd, maar sommige middelen niet altijd in sommige precieze gevallen teruggevonden, GDI cursor handgrepen zijn berucht voor. Natuurlijk, als je een interprocescommunicatiemechanisme, het geheugen in het andere proces toegewezen zou worden vrijgelaten tot die proces bevrijdt of beëindigt.

antwoordde op 01/08/2008 om 18:52
bron van user

stemmen
28

Ik denk dat de "wat is een geheugenlek" en "wat zijn de gevolgen" vragen zijn ook al beantwoord, maar ik wilde nog een paar dingen toe te voegen aan de andere kant vragen ...

Hoe om te begrijpen of uw aanvraag lekken

Een interessante manier is het openen perfmon en sporen toe te voegen voor # bytes in alle stapels en # Gen 2 collecties , in elk geval op zoek alleen op uw proces. Als de uitoefening van een bepaalde functie zorgt ervoor dat de totale bytes te verhogen, en dat het geheugen blijft toegewezen na de volgende Gen 2 collectie, zou je kunnen zeggen dat de functie lekt geheugen.

Hoe te voorkomen

Andere goede adviezen hebben gekregen. Ik wil alleen zeggen dat misschien wel het meest over het hoofd gezien oorzaak van .NET geheugenlekken is om event handlers om objecten toe te voegen zonder ze te verwijderen. Een event handler bevestigd aan een object een vorm van verwijzing naar dat object, zodat zal verzamelen, zelfs nadat alle andere referenties zijn gegaan voorkomen. Altijd onthouden om event handlers los (met behulp van de -=syntaxis in C #).

Is het lek weg te gaan wanneer het proces wordt afgesloten, en hoe zit het met COM Interop?

Wanneer uw proces wordt afgesloten, al het geheugen in kaart gebracht in zijn adresruimte wordt teruggewonnen door het besturingssysteem, met inbegrip van COM-objecten geserveerd van DLL's. Relatief zelden, kunnen COM-objecten worden geserveerd van afzonderlijke processen. In dit geval, wanneer uw proces verlaat, kunt u nog steeds verantwoordelijk voor het geheugen in een COM-server processen die u gebruikt toegewezen.

antwoordde op 15/08/2008 om 17:11
bron van user

stemmen
18

Als u een geheugenlek in .NET diagnosticeren, check deze links:

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

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

Deze artikelen beschrijven hoe u een geheugen dump van uw proces te maken en hoe het te analyseren, zodat u eerst kunt bepalen of uw lek is onbeheerde of beheerd, en als het wordt beheerd, hoe om te achterhalen waar het vandaan komt.

Microsoft heeft ook een nieuwe tool om te helpen met het genereren crash stortplaatsen, om Adplus, genaamd DebugDiag vervangen.

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

antwoordde op 15/08/2008 om 00:16
bron van user

stemmen
18

Ik zou geheugenlekken definiëren als een object niet vrijmaken van alle toegewezen nadat deze is voltooid geheugen. Ik vond dit kan gebeuren in uw toepassing als u gebruik maakt van Windows API en COM (dwz unmanaged code die een bug in het heeft of niet correct behandeld wordt), in het kader en in componenten van derden. Ik heb ook niet schoonmaken is na het gebruik van bepaalde voorwerpen zoals pennen kan het probleem veroorzaken.

Ik persoonlijk hebben geleden Geheugen uitzonderingen die kunnen worden veroorzaakt, maar zijn niet exclusief voor geheugenlekken in dot net toepassingen. (OOM kunnen ook afkomstig zijn van pinning zie Pinning Artical ). Als je niet krijgt OOM fouten of moeten bevestigen als het een geheugenlek waardoor het dan is de enige manier is om uw aanvraag te profileren.

Ik zou ook proberen en zorgen voor het volgende:

a) Alles wat IDisposable implementeert is aangebracht, hetzij met behulp van een definitief blokkeren of de instructie using deze omvatten borstels, pennen etc. (sommige mensen beweren om alles tot niets in aanvulling ingesteld)

b) Alles wat een goede methode is weer gesloten met behulp uiteindelijk of using statement (heeft hoewel ik gebruik niet altijd in de buurt, afhankelijk hebben gevonden als je het object buiten het gebruik van gedeclareerde)

c) Als u gebruik maakt van unmanaged code / windows API is dat deze correct worden afgehandeld na. (Sommige hebben opruimen methoden om middelen vrij te maken)

Ik hoop dat dit helpt.

antwoordde op 01/08/2008 om 18:57
bron van user

stemmen
15

Met behulp van CLR Profiler van Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en is een geweldige manier om welke objecten die het geheugen, wat de uitvoering stroom leads te bepalen tot de oprichting van deze objecten, en ook het toezicht op met live objecten waar op de heap (fragmentatie, LOH, etc.).

antwoordde op 16/08/2008 om 20:54
bron van user

stemmen
14

De beste verklaring van de manier waarop de garbage collector werkt is in Jeff Richters CLR via C # boek, (Ch. 20). Het lezen van dit geeft een geweldige aarding om te begrijpen hoe objecten blijven bestaan.

Een van de meest voorkomende oorzaken van beworteling objecten per ongeluk is door het aansluiten van gebeurtenissen outisde een klasse. Als u aansluiten van een externe gebeurtenis

bv

SomeExternalClass.Changed += new EventHandler(HandleIt);

en vergeet om haak te sturen als je weggooien, dan SomeExternalClass heeft een referentie naar je klas.

Zoals hierboven vermeld, de SciTech geheugen profiler is uitstekend aan te tonen u wortels van objecten u vermoedt lekken.

Maar er is ook een zeer snelle manier om een ​​bepaald type te controleren wordt gebruik gewoon WnDBG (u kunt dit ook gebruiken in de VS.NET onmiddellijke raam terwijl in bijlage):

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

Nu doe iets waarvan u denkt dat de objecten van dat type beschikken (bijvoorbeeld het sluiten van een venster). Het is handig hier om een debug knop ergens die zal draaien hebben System.GC.Collect()een paar keer.

Voer vervolgens !dumpheap -stat -type <TypeName>opnieuw. Als het nummer niet naar beneden gingen, of niet naar beneden zo veel als je verwacht te gaan, dan heb je een basis voor verder onderzoek. (Ik heb deze tip van een seminar gegeven door Ingo Rammer ).

antwoordde op 27/08/2008 om 15:12
bron van user

stemmen
14

Ik denk dat in een beheerde omgeving, zou een lek zijn dat je een onnodige verwijzing houden om een ​​groot deel van het geheugen rond.

antwoordde op 01/08/2008 om 16:19
bron van user

stemmen
10

Waarom doen mensen denken dat een geheugenlek in .NET is niet hetzelfde als elke andere lek?

Een geheugenlek is wanneer je aan een middel vast en laat het niet gaan. U kunt dit doen zowel in beheerde en onbeheerde codering.

Ten aanzien van .NET en andere programmeertools, zijn er ideeën over vuilnis verzamelen, en andere manieren van het minimaliseren van situaties dat uw aanvraag lek zal maken geweest. Maar de beste methode om te voorkomen geheugenlekken is dat je nodig hebt om je onderliggende geheugen model te begrijpen en hoe het werkt, op het platform dat u gebruikt.

In de overtuiging dat GC en andere magie zal opruimen uw puinhoop is de korte weg naar geheugenlekken, en zal moeilijk zijn om later te vinden.

Bij het coderen van unmanaged, u normaal gesproken zorg ervoor om schoon te maken, weet je dat de middelen die u in het bezit van te nemen, uw verantwoordelijkheid op te ruimen, niet van de conciërge zal zijn.

In .NET aan de andere kant, veel mensen denken dat de GC zal opruimen alles. Nou, het doet wat voor je, maar je moet ervoor zorgen dat het zo is. NET heeft wikkel veel dingen, dus je hoeft niet altijd weten of je te maken hebt met een beheerde of onbeheerde bron, en je moet ervoor zorgen dat wat wat je mee bezig bent. Omgaan met lettertypen, GDI-bronnen, active directory, databases etc is typisch dingen die je nodig hebt om uit te kijken.

In beheerde termen zal ik mijn nek op de lijn om te zeggen dat het verdwijnen zodra het proces wordt gedood / verwijderd.

Ik zie veel mensen hebben dit al, en ik hoop echt dat dit zal eindigen. U kunt de gebruiker niet vragen om uw app te beëindigen op te ruimen uw puinhoop! Neem een ​​kijkje op een browser, die kunnen worden IE, FF etc, open dan, zeg, Google Reader, laat het zitten voor een paar dagen, en kijk wat er gebeurt.

Als je dan een ander tabblad in de browser, surf naar een site te openen, sluit vervolgens het tabblad dat de andere pagina die de browser lek gemaakt gehost, denk je dat de browser zal het geheugen vrij te geven? Niet zo met IE. Op mijn computer zal IE gemakkelijk eten 1 GiB geheugen in een korte tijd (ongeveer 3-4 dagen) als ik gebruik maken van Google Reader. Sommige nieuwspagina's zijn nog erger.

antwoordde op 01/09/2008 om 13:19
bron van user

stemmen
10

Ik denk dat in een beheerde omgeving, zou een lek zijn dat je een onnodige verwijzing houden om een ​​groot deel van het geheugen rond.

Absoluut. Ook niet met de methode .Dispose () op wegwerpartikelen waar nodig kan mem lekkage veroorzaken. De eenvoudigste manier om dit te doen is met een blok gebruikt, omdat dit automatisch uitgevoerd .Dispose () aan het einde:

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

En als je een klasse die wordt gebruikt unmanaged objecten te maken, als je IDisposable niet correct bent implementeren, je zou kunnen worden veroorzaakt geheugenlekken voor de gebruikers van uw klasse.

antwoordde op 05/08/2008 om 23:47
bron van user

stemmen
9

Alle geheugenlekken worden opgelost door de beëindiging van het programma.

Lek genoeg geheugen en het besturingssysteem kan besluiten om het probleem voor u op te lossen.

antwoordde op 04/08/2008 om 15:09
bron van user

stemmen
9

Ik zal eens met Bernard als bedoeld in .net wat een mem lek zou zijn.

Je kan je sollicitatie naar het geheugen gebruik Zie profiel, en bepalen dat als zijn het beheren van een veel geheugen wanneer het niet moet je zou kunnen zeggen dat het een lek.

In beheerde termen zal ik mijn nek op de lijn om te zeggen dat het verdwijnen zodra het proces wordt gedood / verwijderd.

Onbeheerde code is zijn eigen beest en als er een lek in het bestaat, zal het een standaard mem volgen. lek definitie.

antwoordde op 01/08/2008 om 16:23
bron van user

stemmen
7

Ook in gedachten houden dat NET heeft twee hopen, waarvan een het grote object heap. Ik geloof objecten van ongeveer 85k of groter worden op deze hoop te zetten. Deze hoop heeft een andere levensduur regels dan de reguliere heap.

Als u het maken van een groot geheugen structuren (Dictionary of List) zou het verstandig om te gaan opzoeken wat de precieze regels zijn.

Voor zover het terugwinnen van het geheugen op het beëindigen van processen, tenzij je met Win98 of deze equivalenten, wordt alles terug vrijgegeven aan de OS op beëindiging. De enige uitzonderingen zijn dingen die cross-proces worden geopend en een ander proces heeft nog steeds de bron geopend.

COM objecten kan lastig tho zijn. Als je altijd gebruik maken van de IDisposepatroon, zult u veilig zijn. Maar ik heb over een paar Interop Assemblies die implementeren draaien IDispose. De sleutel hier is om te bellen Marshal.ReleaseCOMObjectals je klaar bent met het. COM Objects nog standaard COM referentietelling.

antwoordde op 07/08/2008 om 14:17
bron van user

stemmen
6

Ik vond .Net Memory Profiler een zeer goede hulp bij het vinden van geheugenlekken in .Net. Het is niet gratis, zoals de Microsoft CLR Profiler, maar is sneller en meer to the point in mijn mening. EEN

antwoordde op 20/08/2008 om 19:39
bron van user

stemmen
1

Een definitie is: Kan geen onbereikbaar geheugen, dat kan niet meer nieuw proces tijdens de uitvoering van de toewijzing van proces worden toegewezen vrij te geven. Kan meestal worden uitgehard door toepassing van GC technieken of gedetecteerd door geautomatiseerde instrumenten.

Voor meer informatie kunt u terecht op http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .

antwoordde op 27/08/2014 om 16:22
bron van user

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