A számítástechnikában a memóriaszivárgás olyan fajta erőforrás-szivárgás, amely bekövetkezésekor a számítógépes program hibásan kezeli a memóriafoglalásokat olyan módon, hogy a már nem szükséges memória nem szabadul fel. Memóriaszivárgás akkor is bekövetkezhet, amikor egy objektum tárolva van a memóriában, viszont a futó kód nem érheti el. A memóriaszivárgás tünetei több más problémáéhoz hasonlóak, és általában csak egy programozó tudja diagnosztizálni, ha hozzáfér a program forráskódjához.

Helyszivárgás akkor következik be, amikor egy számítógépes program több memóriát használ mint szükséges lenne. Szemben a memóriaszivárgással, ahol a kiszivárgott memória soha nem szabadul fel, a helyszivárgás által elfogyasztott memória felszabadul, de a vártnál később.

A memóriaszivárgás gyakran okozója vagy hozzájárul a szoftver elöregedéséhez, mert kimeríti az elérhető rendszer memóriát, ahogy az alkalmazás fut.

Következmények A memóriaszivárgás lecsökkenti a számítógép teljesítményét az elérhető memória lecsökkentése által. Végső soron, a legrosszabb esetben, túl sok elérhető memória kerül kiosztásra és az összes vagy egy része a rendszernek megáll, vagy a készülék abba hagyja a pontos működést,az alkalmazás megáll, vagy a rendszer jelentősen lelassul a "szemetelés" miatt.

Lehetséges hogy a memóriaszivárgás nem súlyos vagy nem is mutatható ki normál eszközökkel. Modern operációs rendszerekben, az alkalmazás által használt normál memória felszabadul mikor az alkalmazás leáll. Ez azt jelenti, hogy a csak rövid ideig futó programokban előforduló memóriaszivárgást lehet, hogy észre sem vesszük és az csak ritkán súlyos.

Sokkal súlyosabb szivárgások a következők:

ahol a program hosszabb ideig fut, és idővel további memóriát emészt fel, mint például háttér feladatok a szervereken, de különösen beágyazott eszközökben, amiket sokszor évekig is futni hagynak ahol gyakran új memória van kiosztva egyszeri feladathoz, mint például számítógépes játék vagy animált videó képkockáinak megjelenítéséhez ahol a program kérhet memóriát – például megosztott memóriát – amely akkor sem szabadul fel, ha a program leáll ahol a memória nagyon korlátozott, mint például beágyazott rendszerben vagy hordozható eszközben, vagy ahol a program megkezdése nagyon nagy mennyiségű memóriát igényel, kevés tartalékot hagyva a szivárgásra ahol a szivárgás az operációs rendszeren vagy a memóriakezelőn belül történik amikor a rendszereszköz- illesztőprogram okozza a szivárgást olyan operációs rendszerben lévő futtatáskor ami nem szabadítja fel automatikusan a memóriát a program leállításakor.

Egy példa a memóriaszivárgásra A következő pszeudokóddal írt példa megmutatja, hogy miként jön létre egy memóriaszivárgás, és annak hatásait anélkül, hogy bármilyen programozási ismeretre szükségünk lenne. A program ebben az esetben egy nagyon egyszerű szoftver része, amelyet arra terveztek, hogy egy liftet irányítson.A program ezen része fut amikor bárki a lift belsejében megnyomja egy emelet gombját. Amikor egy gomb megnyomódott: Szerezz memóriát, ami felhasználható az emelet számának tárolására Tedd az emelet számát a memóriába A megadott emeleten vagyunk már? Ha igen, akkor nincs más dolgunk: kész Különben: Várj amíg a lift tétlen Menj a megadott emeletre Engedd el a memóriát amit az emelet számának a tárolására használtunk Memóriaszivárgás következne be akkor, ha az kért emelet száma megegyezik azzal amin a lift van; a memória felszabadításának feltétele átugrásra kerülne. Minden egyes alkalommal, amikor ez az eset bekövetkezik, több memória szivárog.

Az ehhez hasonló eseteknek általában nem lenne közvetlen hatása. Az emberek nem gyakran nyomják meg azt a gombot amelyik emeleten már eleve vannak, és más esetekben is, a liftnek lehetséges hogy van elegendő tartalék memóriája hogy ez megtörténhet több száz vagy több ezer alkalommal. A lift azonban egyszer kifogy a memóriából. Ez eltarthat hónapokig vagy évekig is, szóval lehetséges hogy nem fedezik fel ezt a problémát az alapos tesztek ellenére sem.

A következmények kellemetlenek lennének; legjobb esetben a lift nem reagálna arra hogy menjen át más emeletre (például amikor megpróbálja valaki hívni a liftet vagy amikor valaki bent van, és megnyomja egy emelet gombját). Ha a program más részének szüksége van memóriára (például az ajtó kinyitásához és bezárásához tartozó résznek), akkor senki sem léphet be, és ha valaki véletlenül bent van, csapdába esik (feltéve ha az ajtókat nem lehet manuálisan kinyitni).

A memóriaszivárgás a rendszer visszaállításáig tart. Például: ha a lift áramforrását kikapcsolják vagy áramszünet lenne, a program leállna. Az áramellátás újbóli bekapcsolásakor a program újraindulna, és az összes memória ismét elérhető lenne, de a memória szivárgás lassú folyamata a programmal együtt újraindulna, és végül ismét a rendszer helyes működését sértené.

A fenti példában lévő memóriaszivárgás kijavítható, ha a „felszabadítás” műveletet a feltételen kívülre hozzuk: Amikor egy gomb megnyomódott: Szerezz memóriát, ami felhasználható az emelet számának tárolására Tedd az emelet számát a memóriába A megadott emeleten vagyunk már? Ha nem: Várj amíg a lift tétlen Menj a megadott emeletre Engedd el a memóriát amit az emelet számának a tárolására használtunk

Programozási hibák A memóriaszivárgás gyakori hiba a programozásban, különösen olyan nyelvek használatakor, amiknek nincsen beépített automatikus szemétgyűjtése, mint például a C és a C ++ . Jellemzően memóriaszivárgás akkor következik be, amikor egy dinamikusan kiosztott memória elérhetetlen. A memóriaszivárgási hiba túlnyomó jelenléte számos, az elérhetetlen memória felismerésére szolgáló hibakareső eszköz fejlesztéséhez vezetett. ABoundsChecker, a Deleaker, az IBM Rational Purify, a Valgrind, a Parasoft Insure ++, a Dr. Memory és a memwatch néhánya a népszerűbb memória hibakeresők közül C és C++ programokhoz. A "konzervatív" szemétgyűjtő képesség hozzáadható bármely programozási nyelvhez ami hiányol hasonló beépített funkciókat, és hasonló céllal rendelkező könyvtárak elérhetők C és C++ programokhoz is. A konzervatív gyűjtők megtalálják és visszakövetelik a legtöbb, de nem az összes, elérhetetlen memóriát.

Habár a memóriakezelő képes visszaállítani az elérhetetlen memóriát, nem képes felszabadítani a még elérhető és ezért potenciálisan még mindig hasznos memóriát. A modern memóriakezelők ezért technikákat kínálnak a programozók számára, hogy a memóriát különböző szintű hasznossággal szemantikailag jelöljék meg, amelyek megfelelnek az elérhetőség különböző szintjeinek. A memóriakezelő nem szabadít fel olyan objektumot, amely erősen elérhető. Egy objektum erősen elérhető, ha elérhető közvetlenül erős referencia által, vagy közvetve egy erős referenciák láncolata által. (Az erős referencia olyan referencia, amely a gyenge referenciával ellentétben megakadályozza hogy a szemétgyűjtő az objektumot feldolgozza.). Ennek megelőzése érdekében a fejlesztő felelős a referenciák használat utáni megtisztításáért, jellemzően azzal, hogy null-ra állítja a referenciát, ha már nincs rá igény, és ha szükséges, törli az esetleges eseményfigyelőket amelyek erős hivatkozásokat tartanak fenn az objektumra.

Általában az automatikus memóriakezelés robusztusabb és kényelmesebb a fejlesztőknek, mivel nincsen szükségük felszabadító rutinok végrehajtására, vagy nem kell a tisztítás sorrendje miatt aggódniuk, vagy amiatt hogy egy objektumra továbbra is hivatkoznak-e vagy már nem. A programozóknak könnyebb felismerni, ha egy referenciára nincs már szükség, mint azt, hogy ha egy objektumra már nincs hivatkozás. Az automatikus memóriakezelés azonban terhelheti a teljesítményt, és nem küszöböli ki az összes programozási hibát ami memóriaszivárgáshoz vezet.

RAII Az RAII, az erőforrás-beszerzés inicializálásának a rövidítése, a probléma általánosan alkalmazott megközelítése C ++, D és Ada programozási nyelvekben. Ez magába foglalja a hatókörű objektumok társítását a megszerzett erőforrásokkal, és az erőforrások automatikus felszabadítását, ha az objektumok már nem tartoznak a hatókörbe. A szemétgyűjtővel ellentétben, a RAII-nak megvan az az előnye, hogy tudja, egy objektum mikor létezik és mikor nem. Hasonlítsa össze a következő C és C ++ példákat:/* C version */ #include <stdlib.h>

void f(int n) {

int* array = calloc(n, sizeof(int)); do_some_work(array); free(array);

}// C++ version #include <vector>

void f(int n) {

std::vector<int> array (n); do_some_work(array);

}A C verzió, amint a példában megvalósítottuk, határozott kiosztást igényel; a lista dinamikusan van lefoglalva (legtöbbször halmazból van végrehajtva C-ben), és továbbra is létezik, amíg nincsen kifejezetten felszabadítva.

A C ++ verzió nem igényel határozott kiosztást; mindig automatikusan fog bekövetkezni, amint az objektum lista kikerül a hatókörből, beleértve azt is ha kivételt dobunk. Ezzel elkerülve a szemétgyűjtő rendszerek néhány gyengeségét. Mivel az objektumrombolók fel tudnak szabadítani a memórián kívül más erőforrásokat, az RAII segít megelőzni a bemeneti és kimeneti erőforrások szivárgását a kezelés során, amelyet a szemétgyűjtés nem kezel kecsesen. Ezek tartalmaznak nyitott fájlokat, nyitott ablakokat, felhasználói értesítéseket, objektumokat egy grafikus rajzkönyvtárban, szál szinkronizációs primitíveket mint például kritikus szakaszokat, hálózati kapcsolatokat, valamint a Windows rendszerleíró adatbázishoz vagy egy másik adatbázishoz való kapcsolatokat.

Azonban, a RAII helyes használata nem minden esetben könnyű és megvannak a maga buktatói. Például, ha valaki nem elég óvatos, akkor lehet, hogy létrehoz függő mutatókat (vagy referenciákat) az adatok hivatkozással történő visszaadásával csak akkor törölhetők, ha az adatokat tartalmazó objektum kikerül az alkalmazási hatókörből.

A D az RAII és a szemétgyűjtés kombinációját használja, automatikus megsemmisítést alkalmazva, amikor egyértelmű, hogy egy objektumhoz nem lehet hozzáférni az eredeti hatókörén kívül, és szemétgyűjtést egyéb esetekben.

Referenciaszámlálás és ciklikus referenciák A modernebb szemétgyűjtő sémákat gyakran az elérhetőség fogalmára alapozzák – ha nincs használható referencia a kérdéses memóriához, akkor gyűjtésre kerülhet. Más szemétgyűjtő sémák referenciaszámításon alapulhatnak, ahol az objektum felelős annak nyomon követéséről, hogy hány referencia mutat rá. Ha a szám nullára csökken, akkor az objektum várhatóan felszabadítja magát, és lehetővé teszi a memória visszanyerését. A hiba ezzel a modellel hogy képtelen megbirkózni a ciklikus referenciákkal, és ezért manapság programozók nagy része felkészült arra, hogy vállalja a költségesebb jelölési és söprési típusú rendszerek terheit.

A következő Visual Basic kód a kronologikus referenciaszámolásos memóriaszivárgást illusztrálja:Dim A, B Set A = CreateObject("Some.Thing") Set B = CreateObject("Some.Thing") ' Ezen a ponton, mindkét objektumnak van egy referenciája,

Set A.member = B Set B.member = A ' Most már mindkettőnek van két referenciája.

Set A = Nothing ' Még mindig kijuthatunk belőle...

Set B = Nothing ' És most már memóriaszivárgásod van!

EndA gyakorlatban ezt az egyszerű példát azonnal felismernék és kijavítanák. A legtöbb valódi esetben, a referenciák ciklusa át terjed több mint két objektumra és nehezebb a felfedezése.

Az ilyen típusú szivárgások jól ismert példája az AJAX programozási technikák megjelenésével a webböngészőkben a lejárt hallgatói problémában került előtérbe. Az a JavaScript-kód, amely egy DOM elemet társított egy eseménykezelőhöz, és a kilépés előtt nem sikerült eltávolítania a hivatkozást, memóriát szivárogtat (az AJAX weboldalak sokkal tovább tartanak egy DOM-ot életben mint egy tradicionális weboldal, úgyhogy a szivárgás sokkal nyilvánvalóbb volt.) .

Hatások