Memória-szivárgások elszigetelése és javítása MALLOCDEBUG-gal AIX 5.3-on

Címkék

A dinamikus memóriafoglalás kellemes dolog, egyszerűbbé teszi a programozó munkáját. Viszont nagyon fontos, hogy az így allokált memória megfelelően legyen kezelve. A nagy és bonyolult alkalmazások egyre nagyobb problémája a memória-szivárgás, amely akkor léphet fel, ha egy korábban lefoglalt memóriarészre már nincs szükség, de azt elfelejtettük felszabadítani. Az AIX 5.3-ban található MALLOCDEBUG eszközzel lehetőségünk van a memória-szivárgásokat detektálni. A teljes cikk itt.

Hozzászólások

A GC eppen erre valo (pl: itt). Ott nem kell a felszabaditassal foglalkozni, (igy a detektalassal sem) csak lefoglalni mert a gc kitakaritja a mar nem hasznalt, de allokalt teruleteket. Java, C#, etc. meg egy tucatnyi nyelv alapbol tamogatja.

Minél korszakalkotóbb ötlettel állsz elő, annál több hülyén kell átverekedned magadat.

"ha nem vesszük számításba a nem managelt erőforrások kezelését"
Hat nyilvan nem megoldhato mindenutt, de ez nem is volt kerdeses.

"illetve maga a framework/platform"
Mar ahol. Erre vonatkozott az altalanositas.

Minél korszakalkotóbb ötlettel állsz elő, annál több hülyén kell átverekedned magadat.

Ha ennyire ajanlgatod a boehm gc-t, akkor biztos azt is tudod, hogy hogyan mukodik. En ugyanis megneztem, aztan mikor rajottem, hogy micsoda egy gany implementacio, rogton elvetettem. Ugyanis szepen vegigpasztazza a memoriateruleteket, es pointereket keres. Mindenben. Stringekben is! Nevetseges es megbizhatatlan.

1. "A dinamikus memóriafoglalás kellemes dolog, egyszerűbbé teszi
a programozó munkáját." Hát ez szerintem nem így van. A statikus
memóriafoglalás sokkal egyszerűbb és sokkal kevesebb hibát rejt
magában. (Hangsúlyoznám: a dinamikus memóriafoglalás nagyon
fontos dolog, én magam is széleskörben használom, csak az idézett
mondattal vitatkoznék.)

2. Hogy a bánatba lehet megmondani, hogy egy lefoglalt terület
nem kell többé? Hacsak nem fordítás közbeni teljes kódanalízissal.

> Sol omnibus lucet.

Hát, azért a dinamikus foglalás van, amikor tényleg egyszerűbbé teszi a programozó munkáját. Pl. ahhoz képest a fortranban gyakran használt módszerhez képest, hogy a szépen előre megírt szubrutinoknak át kell adni egy előre lefoglalt tömböt (hogy azt a szegmenst ne kelljen minden változtatáskor újrafordítani), a feladatot és a tárméretet (statikusan persze, más nincs) a főprogramban adom meg. És hogy ne kelljen 12 darab (egy adott paraméterből számítható méretű) tömböt átadni, egyet adnak át, és abban tárolják egymás után a program változóit: egy-két vektort, néhány mátrixot, stb.
Amikor egy ilyen programot kell megérteni (pl. netlib numerikus rutinjai), akkor azért az ember úgy érzi, hogy könnyebb lett volna a lefoglalásra/felszabadításra odafigyelni, mint arra, hogy a tömbben hol is van valamelyik vektor.

A 2-höz: pl. nyilvántartom, hogy mutat-e rá pointer. Ha egy lefoglalt területnek eldobom a címét, akkor már nyilván nem kell.

"2. Hogy a bánatba lehet megmondani, hogy egy lefoglalt terület
nem kell többé? Hacsak nem fordítás közbeni teljes kódanalízissal."

Fordítás közben nem tudod megmondani, így ez futásidejű feladat. Egyszerű és elavult módszer a referenciaszámlálás, amikor nyilvántartja az objektum, hogy hány pointer mutat rá, ha egy sem törölhető. Ciklikus adatszerkezeteknél gondot okozhat, de gyenge pointerekkel (nem növeli a számlálót) lehet játszani, ha a nyelv/megvalósítás támogatja.
A mai GC-k általában nem referenciaszámlálással működnek, hanem futásidőben meghatározzák, mely objektumokat lehet elérni. Kiinduló halmaz a vermen lévő "mutatók" által hivatkozott objektumok (plusz statikus adatatgok, stb.), ezt kell mindig növelni a halmazban lévő objektumok által elérhető objektumokkal.
Bocs, ha ez kissé zavaros lett, elég szerteágazó a téma.

KisKresz

"2. Hogy a bánatba lehet megmondani, hogy egy lefoglalt terület
nem kell többé? Hacsak nem fordítás közbeni teljes kódanalízissal."

na ez kissé durva lenne. Szerintem az a kritérium, hogy a szemétgyűjtés pillanatában az adott objektumot már senki sem tudja elérni, mert nincs rá referenciája. Ettől még folyhat a dolog, mivel a felesleges dolgokat valahogy azért jelezni kell, hogy nem kellenek már. Legegyszerübb halál egy globális változó, nincs GC aki azt meri állítani, hogy az már nem kell.

Köszi srácok, megint tanultam valamit (-::

> Sol omnibus lucet.

Ha nincs szukseged BuF/BoF kereseshez, akkor tessek egy reszlet fresh demo endzsi logbol:


[mem-test] Memory management test...
[mem-test]  - total memory: 1342177280
[mem-test]  - available memory: 20971520
[mem-test]  - allocate 1024 byte...
[mem-test]   - passed.
[mem-test]  - allocated memory size: 1024
[mem-test]  - dump allocation list to 'debug.mem' file...
[mem] dump allocation list to 'debug.mem'.
[mem-test]  - dump allocation list to 'debug.mem' file...
[mem] dump allocation list to 'debug.mem'.
[mem-test]   - passed.
[mem-test]  - allocated memory size: 2048
[mem-test]  - dump allocated memory area to file...
[mem-test]  - double free check...

!!! Already released or corrupted memory area: 0x1807200
!!!  - data: 0x00000000
!!!  - SYS_MemFree position: [mem.c:41]
!!!  - SYS_MemGet info: '[mem.c:30] realloc test, buffer'

A hozza tartozo teszt kod:


void memTest( void )
{
 char       * buffer;
 char       * buffer2;

 errClear();

 dlog( "Memory management test...\n" );
 dlog( " - total memory: %d\n",SYS_MemTotal() );
 dlog( " - available memory: %d\n",SYS_MemAvail() );
 dlog( " - allocate 1024 byte...\n" );
 buffer=SYS_MemGet( 1024,"test, buffer" );
 ERR( ( ! buffer ) );
 dlog( " - allocated memory size: %d\n",SYS_MemSize( buffer ) );
 memset( buffer,0x0f,SYS_MemSize( buffer ) );

 dlog( " - dump allocation list to 'debug.mem' file...\n" );
 SYS_MemInfo( "debug.mem" );

 dlog( " - dump allocation list to 'debug.mem' file...\n" );
 SYS_MemInfo( "debug.mem" );

 buffer=SYS_MemRealloc( mem( buffer ),2048,"realloc test, buffer" );
 ERR( ( ! buffer ) );
 dlog( " - allocated memory size: %d\n",SYS_MemSize( buffer ) );

 dlog( " - dump allocated memory area to file...\n" );
 SYS_MemDump( buffer );

// dlog( " - free allocated memory...\n" ); 
 dlog( " - double free check...\n" );
 buffer2=buffer;
 SYS_MemFree( mem( buffer ) );
 SYS_MemFree( mem( buffer2 ) );
}

Termeszetesen kepes arra is, hogy kilepeskor minden felszabaditatlan memoriateruletet felszabadit (ennek kulonosen win32 alatt volt ertelme, s win32/linux/macosx/*BSD/OSF1 alatt is mukodik a lib), s a kod barmely reszen kerheto lista a lefoglalt memoriateruletekrol (ugy, hogy megmutatja, hogy a forrasban hol kerult lefoglalasra).

Mar az eszemet sem tudom mikor irtam meg ezt a reszletet. Ezzel csak arra akartam utalni, hogy kurvara nem cucc ilyet csinalni, es aki kicsit gondolkodik meg is tudja tenni. S nem kell takolni mindenfele libek linkelesevel, betoltesevel, mittomen. Lehet erv az, hogy "jaj ez akkora overhead, mint az allat", de ad 1: fordithato ugy, hogy ez a funkcio nincs bent, de memleak debugnal jol jott. Ad 2: nekem tobbet er azaz informacio, mint a hianyaval nyert plusz 2ms futasi ido.

Jo lesz?

---
pontscho / fresh!mindworkz

Jjja. Ez jo. Egyebkent aki normalis fejlesztoeszkozt hasznal, annak nem kell ilyet irni, mert minden jobb fejlesztoeszkoz tud ilyet. Pl. Free Pascal runtime libekhez van heaptrc (tehat memoria nyomkoveto) unit alapbol ami kb. ugyanezt tudja. Persze tudom Pontscho, hogy te szethackolt testreszabott FPC runtimet hasznalsz, meg amugyis a tied jobb (no irony), sz'al ez rad nem vonatkozik. :)

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

Azt hittem mar megbeszeltuk mi a fasze' van egy 64k intronal kiszedve a sallang. Hogy egy 'begin end.' ne 30k legyen, mint az eredeti runtime-mal, hanem 2.5k. Igen, nehezebb egy fokkal hasznalni, es igen, neha kulonoskepp meg tudja bantani az embert, de ha ezekre rajon, utana mukodik jol. Nembaj, szakerts kerlek.

S szeretem magam irni a cuccaim. Egyreszt mert nem fugg semmilyen license-tol, masreszt erdekelt a tema.

---
pontscho / fresh!mindworkz