3. Dinamikus memóriakezelés

A Pascal hiányosságának tûnik az a megkötés, hogy a változókat elõre deklarálni kell. Így a program elején deklarálhatunk egy tömböt, és a program futása közben derül ki, hogy a szükséges adat (pl. egy file-ból beolvasott hosszú számsorozat) nem fér bele. Ez mindig olyankor fordul elõ, amikor nem ismerjük elõre a feldolgozandó adat mennyiségét. Ezen segít a Pascal azon lehetõsége, hogy a program futása közben is foglalhatunk le memóriát változóknak - ezek lesznek a dinamikus változók, szemben a program deklarációs részében elõre megadott statikus változókkal.

A Pascal memóriaklezelése

Mint tudjuk, minden változónak van neve (azonosítója), típusa, és tartozik hozzá a memóriában egy lefoglalt rész, ahol a változóban lévõ adat helyezkedik el. Mivel a változók által igényelt terület a változók típusából egyértelmûen meghatározható, a program statikus változói által felhasználtandó memória mennyisége már fordításkor kiderül. Az így lefoglalt terület nem lehet nagyobb 64 Kbyte-nál (tehát egy 300 elemû, stringekbõl álló tömb már nem hozható létre!). Eddig statikus memóriakezelésrõl beszélhetünk.

Eljárások hívásakor új változók jönnek létre: az eljárás paraméterei és saját változói. (Ezen kívül a Pascalnak azt is fel kell jegyeznie, hogy hol folytassa az eljáráshíváskor félbeszakadt programot). Mivel ezek a változók futás közben jönnek létre, itt dinamikus memóriakezelésre van szükség. Ezeket az adatokat a Pascal egy STACK (verem) nevû memóriaterületen tárolja. Ha a stack mérete túl kicsi, az csak a program futása közben derül ki („verem túlcsordulás" hiba). Nézzünk példát ilyen programra (az eljárás saját magát hívja, és a stack-en minden híváskor lefoglalásra kerül az a változó):

Procedure Tele;
 Var a:integer;
 Begin
    Tele;
 End;

BEGIN
 Tele;
END.

Végül, a programban saját magunk is foglalhatunk le dinamikusan memóriát. Az így felhasználható memóriaterület neve HEAP (halom). A heap mérete tetszõlegesen nagy lehet (pontosabban: akkora, mint a program rendelkezésére álló memóriaméret, ami különbözõ tényezõktõl függ). Az egyetlen korlátozás, hogy a benne egyszerre lefoglalt memóriaméret nem lehet nagyobb 64 Kbyte-nál. Így pl. itt sem hozhatunk létre egy 300 elemû, stringekbõl álló tömböt, de két 150 elemût már igen.

A stack és a heap méretét fordításkor megadhatjuk a
   {$M stack,heapmin,heapmax}
úgynevezett fordítási direktívával (compiler directive). A fordítási direktívákat a Pascal fordítás közben értékeli ki és hajtja végre, a lefordított program futása közben már nem játszanak szerepet. stack paraméter a stack méretét, heapmin és heapmax a heap méretét (legalább és legfeljebb) adja meg. Ha a rendelkezésre álló memória heapmin-nél kisebb, a program nem indul el, és semmiképpen nem foglal le heapmax-nél több memóriát. Alapértelmezés szerint a futó program az összes szabad memóriát lefoglalja.

A heap kezelése és a pointerek

Dinamikus változók használatánál a programozónak az eddiginél többet kell foglalkozni a memóriakezeléssel, melyet egyébként a Pascal automatikusan végez. A változó létrehozásakor le kell foglalni egy megfelelõ méretû memóriaterületet, és gondoskodni kell annak felszabadításáról, ha a változóra már nincs szükség. Ehhez tudni kell, hogy a dinamikus változó hol helyezkedik el a memóriában, és mennyi helyet foglal le.

A pointer olyan változó, mely a memória adott helyére mutat. Ehhez egy új típust kell bevezetnünk.

Típus nélküli pointerek

típus      értékek
POINTER    memóriacím vagy NIL

Ha egy pointer típusú változó (továbbiakban pointer) értéke NIL, az azt jelenti, hogy a pointer még nem mutat sehová. (Célszerûen ez a pointer kezdõértéke.) A memóriafoglalás és -felszabadítás a következõ utasításokkal történik:

A Getmem utasítás hatására a Pascal lefoglal egy megadott méretû memóriarészt a heap területen, a pointer értéke pedig erre a memóriacímre fog mutatni. Ezen kívül azonban nem sokat kezdhetünk a lefoglalt memóriával: azon kívül, hogy a Pascal egyes eljárásai igénylik, hogy adattárolás céljából memóriát foglaljunk számukra (ld. Getimage utasítás), az ilyen memóriakezelés már assembly szintû programozást igényel. Ezzel a pointer-fajtával a továbbiakban nem foglalkozunk.

Típusos pointerek

A típusos pointer esetén a Pascal azt is nyilvántartja, hogy az a memóriacím, ahová a pointer mutat, milyen típusú adatot rejt. Ekkor egyrészt automatikussá válik a lefoglalt memória méretének meghatározása (a programozónak nem kell vele foglalkozni), másrészt ezt a memóriarészt az adott típusú változóként használni is tudjuk. Típusos pointer típusa:

ahol az alaptípus a pointer által mutatott memóriarészen elhelyezkedõ adat típusa. Így pl. az ^integer olyan pointer típusa, mely a memóriában egy integer típusú adatra mutat. Ezt a memóriarészt dinamikus változóként a

hivatkozással használhatjuk, így közönséges változóként fog viselkedni (ez az a dinamikus változó, amelyre a pointer mutat). A memóriafoglalás és -felszabadítás utasításai:

Nézzünk egy példát dinamikus változó létrehozására:

VAR p:^integer
BEGIN
 New(p);
 Readln(p^);
 Writeln(p^);
 Dispose(p);
END.

A példában p^ egyszerû változóként viselkedett, melyet a program futása közben hoztunk létre. A következõ példa létrehoz 2, 150 elemû stringbõl álló tömböt, így a pointerek használatával máris túlléptük a statikus memóriakezelés 64 Kbyte-os korlátját:

TYPE Tomb=array[1..150] of string;
VAR p,q:^Tomb;
    i:integer;
BEGIN
 New(p);
 New(q);
 For i:=1 to 150 do begin
    p^[i]:='Egyik szöveg';
    q^[i]:='Másik szöveg';
 end;
 Dispose(p);
 Dispose(q);
END.

Itt p^ és q^ olyan, mint két 150 elemû tömb. p és q pointereket közvetlenül nem használjuk. A statikus memóriában csak a pointerek helyezkednek el, egy pointer pedig (mivel tartalma csak egy memóriacím) alig foglal memóriát. Figyeljük meg, hogy a típusokkal és pointerekkel való munka során a TYPE deklaráció egyre fontosabbá válik, és már nem csak a program áttekinthetõbbé tétele miatt (ld. még elsõ rész, 9. fejezet).

A dinamikus adatszerkezetekkel való további foglalkozás a rekurzió fogalmának ismeretét követeli meg (ld. a B. függelékben).

Következõ fejezet
Elõzõ fejezet
Tartalomjegyzék
Honlap