Hukommelsestap

En minnelekkasje (bedre kjent under det engelske uttrykket minnelekkasje ) er en programvarefeil som oppstår når en blokk med reservert minne ikke frigjøres i et dataprogram . Det oppstår ofte fordi alle referanser til det minneområdet går tapt før de frigjøres.

Avhengig av hvor mye minne som er lekket og hvor lenge programmet kjører , kan dette problemet føre til utmatting av tilgjengelig minne på datamaskinen .

Dette problemet oppstår hovedsakelig i de programmeringsspråkene der minneadministrasjon er manuell (hovedsakelig C eller C++), og derfor er det programmereren som må vite i hvilket øyeblikk minnet kan frigjøres. Andre språk bruker en søppeloppsamler eller referansetelling som automatisk utfører denne utgivelsen. Lekkasjer på disse språkene er imidlertid fortsatt mulig hvis programmet akkumulerer referanser til objekter, og dermed forhindrer samleren fra å avskrive dem.

Det er flere måter å bekjempe dette problemet. En måte er å bruke en søppelsamler selv om det ikke er en standard del av språket. Den mest kjente søppelsamleren som brukes på denne måten er Boehm-Demers-Weiser konservative søppelsamler . Andre teknikker som brukes er bruk av referansetellingsskjemaer eller bruk av minnepuljer (mindre populær teknikk, brukt i Apache-serveren og i Subversion-versjonssystemet).

Det finnes også verktøy for å «lytte» til et program og oppdage lekkasjer. Et av de mest kjente verktøyene er Valgrind .

RAII

" Resource Acquisition Is Initialization " , ofte referert til med akronymet RAII (for "Resource Acquisition Is Initialization"), er et populært designmønster i forskjellige objektorienterte programmeringsspråk som C++ og Ada . RAII adresserer minnelekkasjer ved å kartlegge objekter til innhentede ressurser, og automatisk frigjøre ressurser når objekter avslutter livet. I motsetning til søppelinnsamling har RAII fordelene ved å: vite når objekter eksisterer, og vite når de ikke gjør det. Du kan sammenligne følgende eksempler i C og C++:

/* C-versjon */ #include <stdlib.h> void f ( int n ) { int * array = calloc ( n , størrelse på ( int )); utføre_andre_operasjoner (); gratis ( array ); } // C++ versjon. #inkluder <vektor> void f ( int n ) { std :: vektor < int > matrise ( n ); utføre_andre_operasjoner (); }

C-versjonen krever at utvikleren gjør minnefrigjøring, i motsetning til C++-versjonen. Dette unngår overbelastning av søppeloppsamlingsordninger , og kan til og med brukes på andre ressurser som:

  • "Handterer" filer, som "merk-og-fei" søppelinnsamling ikke håndterer like effektivt.
  • Vinduer som må lukkes.
  • Ikoner i systemstatusfeltet skal skjules.
  • Synkroniseringskode som monitorer, kritiske seksjoner osv. som må frigjøres for å la andre tråder få tak i dem.
  • "Håndterer" til Windows-registret som er åpne.
  • Nettverkstilkoblinger.
  • Windows GDI-objekter.
  • Handlinger som skal utføres når en funksjon (eller kodeblokk ) avsluttes på et hvilket som helst mulig punkt (handlingen utføres av destruktoren til et objekt opprettet når funksjonen starter).

Minnelekkasjer på språk med søppelsamler

Minnelekkasjer i språk som JavaScript er også vanlig, for eksempel kan de oppstå når det er sirkulære referanser mellom objekter. For eksempel har et vindusobjekt en referanse til hver av kontrollene (knapper, bilder osv.), på sin side har hver kontroll en referanse til vinduet som inneholder det. Minnehøstere som bruker referansetelling , innser kanskje ikke at et vindu ikke lenger brukes fordi det fortsatt er en referanse til det (fra kontrollene).

Disse minnelekkasjene er svært vanlige når du programmerer uforsiktig. Det finnes teknikker for å unngå dem (fjern for eksempel noen av referansene for å kutte sirkelen).

I JavaScript forekommer sirkulære referanser også når funksjoner er skrevet inne i andre, fordi når en funksjon er skrevet inne i en annen, beholdes en referanse til den som inkluderer den (for å bruke variablene). Konseptet med lukking forklarer denne atferden.

Se også