Anatomy of a "Memory Leak"

stemmer
163

I .NET perspektiv:

  • Hva er en minnelekkasje ?
  • Hvordan kan du avgjøre om søknaden lekkasjer? Hva er effekten?
  • Hvordan kan du unngå en minnelekkasje?
  • Hvis programmet har minnelekkasje, det går unna når prosessen går ut eller blir drept? Eller har minnelekkasjer i programmet påvirke andre prosesser på systemet selv etter prosessen ferdigstillelse?
  • Og hva med uovervåkede kode tilgjengelig via COM Interop og / eller P / Invoke?
Publisert på 01/08/2008 klokken 15:12
kilden bruker
På andre språk...                            


15 svar

stemmer
109

Den beste forklaringen jeg har sett er i kapittel 7 i de frie Foundations of Programmering e-bok .

I utgangspunktet i .NET et minne lekkasje oppstår når refererte objekter er forankret, og kan derfor ikke søppel samles. Dette skjer ved et uhell når du holder på å referanser utover den tiltenkte omfang.

Du vet at du har lekkasjer når du begynner å få OutOfMemoryExceptions eller minnebruken går opp utover hva du forventer ( PerfMon har fine minne tellere).

Forstå .NET minne modellen er den beste måten å unngå det. Spesielt forstå hvordan det fungerer søppelsamler og hvordan referanser arbeid - igjen, viser jeg deg til kapittel 7 i e-bok. Vær også oppmerksom på vanlige fallgruvene, sannsynligvis den mest vanligste er hendelser. Hvis objektet A er registrert i en hendelse på objekt B , så protesterer En vil holde seg rundt til objekt B forsvinner fordi B har en referanse til en . Løsningen er å avregistrere hendelsene når du er ferdig.

Selvfølgelig vil en god hukommelse profil lar deg se dine objekt grafer og utforske hekkende / referanse av dine gjenstander for å se hvor referanser kommer fra og hva roten objektet er ansvarlig ( rød-gate maur profil , JetBrains dotMemory, memprofiler er virkelig god valg, eller du kan bruke tekst-bare WinDbg og SOS , men jeg vil sterkt anbefale et kommersielt / visuelt produkt med mindre du er en ekte guru).

Jeg tror uovervåkede kode er underlagt sine typiske minnelekkasjer, bortsett fra at felles referanser er administrert av søppelinnsamler. Jeg kan ta feil om dette siste punktet.

Svarte 01/08/2008 kl. 15:28
kilden bruker

stemmer
33

Strengt tatt er en minnelekkasje forbruker minne som er "ikke lenger brukes" av programmet.

"Ikke lenger brukes" har mer enn én betydning, kan det bety "ikke mer referanse til det", det vil si helt uopprettelig, eller det kan bety, referert, utvinnbare, ubrukt men programmet holder referanser uansett. Bare den senere gjelder NET for perfekt administrerte gjenstander . Men ikke alle klasser er perfekt, og på et tidspunkt en underliggende uovervåkede implementering kan lekke ressurser permanent for denne prosessen.

I alle tilfeller bruker programmet mer minne enn strengt nødvendig. De sider effekter, avhengig av mengde lekket, kunne gå fra ingen til nedgangen forårsaket av overdreven samling, til en rekke minneunntagelser og til slutt en fatal feil fulgt av tvungen prosess oppsigelse.

Du vet at programmet har et minneproblem når overvåking viser at mer og mer minne er allokert til prosessen etter hver søppelrydding syklus . I så fall er du enten holde for mye i minne, eller noen underliggende uovervåkede implementering lekker.

For de fleste lekkasjer, ressurser blir gjenvunnet når prosessen er avsluttet, men noen ressurser ikke alltid gjenfunnet i noen presise tilfeller GDI markør håndtak er beryktet for det. Selvfølgelig, hvis man har en mekanisme for interkommunikasjonsmekanisme, minne allokert i den andre prosessen vil ikke bli frigjort før den prosessen frigjør den eller opphører.

Svarte 01/08/2008 kl. 17:52
kilden bruker

stemmer
28

Jeg tror "hva er en minnelekkasje" og "Hva er effekten" spørsmål er besvart godt allerede, men jeg ønsket å legge til noen flere ting på de andre spørsmålene ...

Hvordan å forstå om din søknad lekkasjer

En interessant måte er å åpne perfmon og legge spor for # bytes i alle hauger og # Gen 2 samlinger , i hvert fall ser bare på prosessen. Hvis du trener en bestemt funksjon fører den totale bytes å øke, og at minnet forblir tildelt etter neste Gen 2 samling, kan du si at funksjonen lekker minne.

Hvordan forebygge

Andre gode meninger har fått. Jeg ville bare legge til at kanskje den mest oversett årsak til NET minnelekkasjer er å legge hendelsesbehandlinger til objekter uten å fjerne dem. En hendelse håndterer er festet til en gjenstand som er en form for referanse til den gjenstand, så vil forhindre samling selv etter at alle andre referanser har gått. Husk alltid å koble hendelsesbehandlinger (med -=syntaks i C #).

Har lekkasjen gå bort når prosessen utganger, og hva med COM Interop?

Når prosessen avsluttes, all hukommelse kartlagt i adressen plass er gjenvunnet av OS, inkludert eventuelle COM-objekter servert fra DLL-filer. Relativt sjelden, kan COM-objekter serveres fra separate prosesser. I dette tilfellet, når prosessen avsluttes, kan du fortsatt være ansvarlig for minnebruken i noen COM server prosesser som du brukte.

Svarte 15/08/2008 kl. 16:11
kilden bruker

stemmer
19

Hvis du trenger å diagnostisere en minnelekkasje i .NET, sjekk disse lenkene:

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

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

Disse artiklene beskriver hvordan du oppretter en minnedump av prosessen og hvordan å analysere det slik at du kan først finne ut om lekkasjen er uovervåkede eller administrert, og hvis det er klart, hvordan å finne ut hvor det kommer fra.

Microsoft har også en nyere verktøy for å hjelpe til med å generere crash dumper, for å erstatte ADPlus, kalt DebugDiag.

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

Svarte 14/08/2008 kl. 23:16
kilden bruker

stemmer
19

Jeg vil definere minne lekkasjer som et objekt ikke frigjøre alt minnet allokert etter at den er fullført. Jeg har funnet dette kan skje i søknaden din hvis du bruker Windows API og COM (dvs. uovervåkede kode som har en feil i det eller ikke blir forvaltet riktig), i rammen og i tredjeparts komponenter. Jeg har også funnet ikke Vasking etter bruk av visse gjenstander som penner kan forårsake problemet.

Jeg personlig har lidd Out of Memory Unntak som kan være forårsaket, men er ikke eksklusivt for minnelekkasjer i Dot Net applikasjoner. (Oom kan også komme fra låsing se Pinning artical ). Hvis du ikke får oom feil eller behov for å bekrefte om det er en minnelekkasje som forårsaker det da den eneste måten er å profilere din søknad.

Jeg vil også prøve og sikre følgende:

a) Alt som implementerer Idisposable er plassert enten ved hjelp av en endelig blokkere eller bruke uttalelsen disse inkluderer pensler, penner osv (noen hevder å sette alt til ingenting i tillegg)

b) Alt som har et nært metode lukkes igjen med til slutt, eller ved hjelp av utsagn (selv om jeg har funnet bruker ikke alltid nær avhengig av om du erklært objektet utenfor hjelp statement)

c) Dersom du bruker uovervåkede kode / vinduer API er at disse er behandlet korrekt etter. (Noen har rydde opp metoder for å frigjøre ressurser)

Håper dette hjelper.

Svarte 01/08/2008 kl. 17:57
kilden bruker

stemmer
15

Den beste forklaringen på hvordan søppelinnsamler fungerer er i Jeff Richters CLR via C # bok, (kap. 20). Leser dette gir en god jording for å forstå hvordan objekter vedvarer.

En av de vanligste årsakene til rooting gjenstander tilfeldigvis er ved å hekte opp hendelser outisde en klasse. Hvis du koble opp en ekstern hendelse

f.eks

SomeExternalClass.Changed += new EventHandler(HandleIt);

og glemmer å hekte til det når du kaster, så SomeExternalClass har en ref til klassen.

Som nevnt ovenfor, SciTech minne profiler er gode til å vise deg røttene av objektene du mistenker lekker.

Men det er også en veldig rask måte å sjekke en bestemt type er bare bruke WnDBG (du kan også bruke dette i VS.NET umiddelbar vinduet mens vedlagt):

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

Nå gjør noe som du tror vil kaste objekter av denne typen (f.eks lukke et vindu). Det er praktisk her for å ha en debug-knapp et sted som vil kjøre System.GC.Collect()et par ganger.

Så løpe !dumpheap -stat -type <TypeName>igjen. Hvis nummeret ikke gikk ned, eller ikke gå ned så mye som du forventer, da har du et grunnlag for videre etterforskning. (Jeg fikk dette tipset fra et seminar gitt av Ingo Rammer ).

Svarte 27/08/2008 kl. 14:12
kilden bruker

stemmer
15

Ved hjelp av CLR Profiler fra Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en er en fin måte å finne ut hvilke gjenstander holder minne, hva gjennomføring flyt fører til etableringen av disse gjenstander, og også å overvåke hvilke objekter levende der på haugen (fragmentering, LOH, etc.).

Svarte 16/08/2008 kl. 19:54
kilden bruker

stemmer
14

Jeg antar i et administrert miljø, vil en lekkasje være deg holde en unødvendig referanse til en stor del av minnet rundt.

Svarte 01/08/2008 kl. 15:19
kilden bruker

stemmer
11

Hvorfor tror folk at en minnelekkasje i .NET er ikke det samme som alle andre lekkasjen?

En minnelekkasje er når du kobler til en ressurs og ikke la det gå. Du kan gjøre dette både i forvaltet og uovervåkede koding.

Angå NET, og andre programmeringsverktøy, har det vært ideer om søppel innsamling, og andre måter å minimere situasjoner som vil gjøre din søknad lekkasje. Men den beste metoden for å hindre minnelekkasjer er at du trenger å forstå underliggende minnemodell, og hvordan ting fungerer, på plattformen du bruker.

Tro at GC og annen magi vil rydde opp i rotet er kort vei til minnelekkasjer, og vil være vanskelig å finne senere.

Når koding uovervåkede, du normalt sørge for å rydde opp, du vet at de ressursene du tar tak i, vil være ditt ansvar å rydde opp, ikke vaktmester.

I .NET på den annen side, mange mennesker tror at GC vil rydde opp alt. Vel, det gjør det litt for deg, men du må sørge for at det er slik. NET har vikle mange ting, slik at du ikke vet om du har å gjøre med en styrt eller ikke-administrerte ressurs, og du må sørge for at det hva du arbeider med. Håndtering av fonter, ressurser GDI, Active Directory, databaser etc er vanligvis ting du må se opp for.

I administrerte vilkår vil jeg sette min hals på linjen for å si det går bort når prosessen er drept / fjernet.

Jeg ser mange mennesker har dette selv, og jeg håper virkelig dette vil ende. Du kan ikke be brukeren om å avslutte appen din for å rydde opp i rotet! Ta en titt på en nettleser, kan det være IE, FF etc, så åpen, si, Google Reader, la det bli for noen dager, og se på hva som skjer.

Hvis du deretter åpner en annen fane i nettleseren, surfe på noen nettsted, deretter lukker fanen som vert den andre siden som gjorde nettleseren lekkasje, tror du nettleseren vil frigjøre minne? Ikke så med IE. På min datamaskin IE vil lett spise en GiB minne i løpet av kort tid (ca 3-4 dager) hvis jeg bruker Google Reader. Noen newspages er enda verre.

Svarte 01/09/2008 kl. 12:19
kilden bruker

stemmer
10

Jeg antar i et administrert miljø, vil en lekkasje være deg holde en unødvendig referanse til en stor del av minnet rundt.

Absolutt. Også, ikke ved hjelp av .Dispose () -metoden på engangsgjenstander når det er hensiktsmessig kan føre til mem lekkasjer. Den enkleste måten å gjøre det på er med en ved hjelp av blokk fordi den automatisk utfører .Dispose () på slutten:

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

Og hvis du oppretter en klasse som bruker administrerte objekter, hvis du ikke implementere IDisposable riktig, du kan være årsaken minnelekkasjer for klassens brukere.

Svarte 05/08/2008 kl. 22:47
kilden bruker

stemmer
10

Jeg vil stemme med Bernard om i .net hva en mem lekkasje ville være.

Du kan profilere din søknad for å se sin minnebruk, og finner ut at dersom administrerende mye minne når det ikke bør være du kan si det har en lekkasje.

I administrerte vilkår vil jeg sette min hals på linjen for å si det går bort når prosessen er drept / fjernet.

Uovervåkede kode er dens eget dyr, og hvis det finnes en lekkasje i det, vil det følge en standard minnekort. lekke definisjon.

Svarte 01/08/2008 kl. 15:23
kilden bruker

stemmer
9

Alle minnelekkasjer er løst av programmet avsluttes.

Lekke nok minne og operativsystemet kan beslutte å løse problemet på dine vegne.

Svarte 04/08/2008 kl. 14:09
kilden bruker

stemmer
7

Også huske på at NET har to hauger, et vesen det store objektet haugen. Jeg tror objekter av omtrent 85k eller større er satt på denne haugen. Denne haugen har forskjellig levetid regler enn den vanlige haugen.

Hvis du lager store minnestrukturer (ordbok eller liste tallet) ville det klokt å gå oppslaget hva den eksakte reglene er.

Såvidt Reclaiming minnet på prosessen oppsigelse, med mindre din kjører Win98 eller det ekvivalenter, alt er sluppet tilbake til OS på oppsigelse. De eneste unntakene er ting som er åpnet på tvers av prosessen og en annen prosess har fortsatt ressursen åpen.

COM-objekter kan være vanskelig tho. Hvis du alltid bruke IDisposemønster, vil du være trygg. Men jeg har kjørt over noen interoperabilitets forsamlinger som implementerer IDispose. Nøkkelen her er å ringe Marshal.ReleaseCOMObjectnår du er ferdig med det. COM objekter fortsatt bruke standard COM referansetelling.

Svarte 07/08/2008 kl. 13:17
kilden bruker

stemmer
6

Jeg fant Net Memory Profiler en veldig god hjelp når finne minnelekkasjer i Net. Det er ikke gratis som Microsoft CLR Profiler, men er raskere og mer til poenget etter min mening. EN

Svarte 20/08/2008 kl. 18:39
kilden bruker

stemmer
1

En definisjon er: ikke frigjøre nås minne, noe som ikke lenger kan fordeles på ny prosess under utførelse av tildeling av prosessen. Det kan for det meste herdes ved anvendelse av GC-teknikker eller detekteres ved hjelp av automatiske verktøy.

For mer informasjon, vennligst besøk http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html .

Svarte 27/08/2014 kl. 15:22
kilden bruker

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