8. el őadás dinamikus mem óriakezelés. mutatók. láncolt adatszerkezetek

100
8. előadás Dinamikus memóriakezelés. Mutatók. Láncolt adatszerkezetek.

Upload: cain

Post on 06-Jan-2016

34 views

Category:

Documents


1 download

DESCRIPTION

8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek. Egy program a memóriában. Futtatás közben a program által használt tár felépítése: kód (statikus) adatok végrehajtási verem dinamikus tárterület (heap). Változók leképzése a memóriára. Statikus - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

8. előadásDinamikus memóriakezelés. Mutatók. Láncolt adatszerkezetek.

Page 2: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

2

Egy program a memóriában

Futtatás közben a program által használt tár felépítése:– kód– (statikus) adatok– végrehajtási verem– dinamikus tárterület (heap)

Page 3: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

3

Változók leképzése a memóriára

Statikus– A fordító a tárgykódban lefoglal neki helyet

Automatikus– Futás közben a végrehajtási vermen jön létre és

szűnik meg Dinamikus

Page 4: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

4

Dinamikus változók

Dinamikus tárterület– Ahonnan a programozó allokátorral tud

memóriát foglalni– Explicit felszabadítás vagy szemétgyűjtés

Mutatók és referenciák Utasítás hatására jön létre (és esetleg

szabadul fel) a változó– Statikus és automatikus: deklaráció hatására

Page 5: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

5

Típusosztályok az Adában

elemi típusokskalár típusok

diszkrét típusokfelsorolásiegész (előjeles, ill.

moduló)valós típusok (fix- és lebegőpontos)

mutató típusokösszetett típusok

tömb, rekord stb.

Page 6: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

6

Mutató típusok

A dinamikus változók használatához Ada: access típusok

type P is access Integer;X: P;

Dinamikus változó létrehozásaX := new Integer;

Dinamikus változó elérése a mutatón keresztülX.all := 3;

Dinamikus változó megszüntetése…később…

Page 7: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

7

Mutató típusok definiálása

type P is access Integer;

type Q is access Character;

type R is access Integer;

Meg kell adni, hogy mire mutató mutatók vannak a típusban: gyűjtőtípus

P, Q és R különböző típusok

Page 8: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

8

Mutatók a C++ nyelvben

Nincsen önálló „mutató típus” fogalom Mutató típusú változók

int *x; Nem lehet két különböző

„int-re mutató mutató” típust definiálni

A Javában csak implicit módon jelennek meg a mutatók

Page 9: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

9

Mutató, ami sehova sem mutat

Nullpointer Az Adában: a null érték Minden mutató típusnak típusértéke

type P is access Integer;

X: P := null;

Y: P; -- implicit módon null-ra inicializálódik

Page 10: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

10

Hivatkozás null-on keresztül

type P is access Integer;

X: P := null;

N: Integer := X.all;

Constraint_Error

futási idejű hiba

Page 11: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

11

Indirekció

A mutatókkal indirekt módon érjük el a változóinkat. (mutató memóriacím)

X := new Integer;

Az X változó egy újonnan (a heap-en) létrehozott változóra mutat: X.all

X.all := 1;X.all := X.all + 1;

balérték

Page 12: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

12

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

Indirekció (1)

Page 13: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

13

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

Y

X

Indirekció (2)

Page 14: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

14

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

Y

X

?

Indirekció (3)

Page 15: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

15

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

?Y

X

?

Indirekció (4)

Page 16: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

16

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

3Y

X

?

Indirekció (5)

Page 17: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

17

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

3Y

X

?

Indirekció (6)

Page 18: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

18

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

5Y

X

?

Indirekció (7)

Page 19: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

19

type P is access Integer;X, Y: P;

X := new Integer;X := new Integer;X.all := 3;Y := X;X.all := 5;X := new Integer;

5Y

X

?

?

Indirekció (8)

Page 20: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

20

Alias kialakulása

Ha ugyanazt a változót többféleképpen is elérem Például cím szerinti paraméterátadásnál Például mutatók használatával

X := new Integer;

X.all := 3;

Y := X; Veszélyes, de hasznos

– C++ referenciák

3Y

X

Page 21: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

21

A dinamikus memóriakezelés baja

Mikor szabadítsunk fel egy változót? Dinamikus változó élettartama Az alias-ok miatt bonyolult

Ha felszabadítom: nem hivatkozik még rá valaki egy másik néven?

Ha nem szabadítom fel: felszabadítja más?

Page 22: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

22

Ha felszabadítom

int *x = new int;

int *y = identitás(x);

delete x;

*y = 1; // illegális memóriahivatkozás

int *identitás( int *p )

{

return p;

}

Page 23: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

23

Ha nem szabadítom fel

int *x = new int;x = másolat(x);// memory leak

int *másolat( int *p ){

int *q = new int;*q = *p;return q;// return new int(*p);

}

Page 24: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

24

Megoldások

Legyen ügyes a programozó Legyen szemétgyűjtés Használjunk automatikus változókat

– Ott a hatókörhöz kapcsolódik az élettartam– C++: automatikus objektum destruktora

Page 25: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

25

Szemétgyűjtés

Garbage collection Ne a programozónak kelljen megszüntetnie a nem

használt dinamikus változókat A futtató rendszer megteszi helyette Nő a nyelv biztonságossága A hatékonyság picit csökken

(a memóriaigény és a futásiidő-igény is nő) Megéri (kiforrott szemétgyűjtési algoritmusok) LISP (1959), Ada, Java, modern nyelvek

Page 26: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

26

Felszabadítás az Adában

Szemétgyűjtéssel (alapértelmezett)– A típusrendszer az alapja– Egészen más, mint például a Javában

Explicit felszabadítással– Ada.Unchecked_Deallocation– A hatékonyság növelése érdekében– Van, amikor csak így lehet

Page 27: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

27

Szemétgyűjtés az Adában

A dinamikus változó felszabadul, amikor a létrehozásához használt mutató típus megszűnik

Ekkor már nem férek hozzá a változóhoz– alias segítségével sem,– csak ha nagyon trükközök

Tehát biztonságos a felszabadítás

Page 28: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

28

„Automatikus” mutató típus esetén

procedure A is

type P is access Integer;

X: P := new Integer;

begin

X.all := 3;

end A;

P megszűnik,

és X.all is

Page 29: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

29

A mutató és a mutatott objektum élettartama más hatókörhöz kötöttprocedure A is

type P is access Integer;

X: P;

begin

declare

Y: P := new Integer;

begin

Y.all := 3;

X := Y;

end;

end A;

Y megszűnik, de

Y.all még nem

Page 30: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

30

„Statikus” mutató típus

package A is

type P is access Integer;

end A;

X: P := new Integer;

Ha az A egy

könyvtári egység,

az X.all a program

végéig létezik

Page 31: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

31

A programozó szabadít fel

Ha a mutató típus a program végéig létezik, nincs szemétgyűjtés

A programozó kézbe veheti a felszabadítást– Nem csak ilyenkor veheti kézbe…

Ada.Unchecked_Deallocation sablon– ez felel meg a C++ delete-jének

Page 32: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

32

Ada.Unchecked_Deallocation

with Ada.Unchecked_Deallocation;procedure A is

type P is access Integer;procedure Free is new Ada.Unchecked_Deallocation(Integer,P);X: P := new Integer;Y: P := X;

beginFree(X);

Y.all := 1; -- definiálatlan viselkedésend A;

Page 33: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

33

Mire használjuk a dinamikus változókat?

Láncolt adatszerkezetekhez– Ha a méret vagy a szerkezet (sokat) változik futás

közben (beszúró, törlő műveletek)– Ha nem kell az adatelemeket "közvetlenül" elérni

(indexelés helyett csak "sorban")– Listák, fák, gráfok, sorozat típusok

Változó, vagy ismeretlen méretű adatok kezelésére– A gyűjtőtípus ilyenkor egy paraméteres típus

Page 34: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

34

Dinamikus méretű objektumok

A gyűjtőtípus lehet - diszkriminánsos rekord- határozatlan méretű tömb

Megszorítás megadása: legkésőbb allokáláskor Az allokált objektum mérete nem változtatható meg

type PString is access String;X: PString; -- akármilyen hosszú szövegre mutathat

X := new String(1..Méret);X := new String ' ("Alma"); -- allokálás + inicializálásX := new String ' (S); -- másolat az S stringről

Page 35: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

35

Blokk utasítás vagy mutató

procedure A isN: Natural;

beginGet(N);declare

V: Verem(N);begin

…end;

end A;

procedure A isN: Natural;type P_Verem is access Verem;V: P_Verem;

beginGet(N);V := new Verem(N);…

end A;

Page 36: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

36

Amikor mutató kell

procedure A istype P_Verem is access Verem;function Létrehoz return P_Verem is

N: Positive;begin

Get(N);return new Verem(N);

end Létrehoz;V: P_Verem := Létrehoz;

begin…

end A;

ha vissza kell adni

egy dinamikus méretű

objektumot

Page 37: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

37

Láncolt adatszerkezet: rekurzív típus

Pl. Lista adatszerkezet megvalósításához Mutató: egy csúcsra mutat Csúcs: tartalmaz adatot, valamint mutatót a

következő elemre Melyiket definiáljuk előbb?

Page 38: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

38

Rekurzív típusok definiálása

type Csúcs;

type Mutató is access Csúcs;

type Csúcs is record

Adat: Elem;

Következő: Mutató;

end record;

deklaráljuk a típust

Page 39: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

39

Átlátszatlan rekurzív típusok

package Listák istype Csúcs is private;type Mutató is private;…

privatetype Mutató is access Csúcs;type Csúcs is record

Adat: Elem; Következő: Mutató;

end record;end Listák;

Page 40: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

40

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.all.Adat := E;

Új.all.Következő := M.all.Következő;

M.all.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (1)

Page 41: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

41

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.all.Adat := E;

Új.all.Következő := M.all.Következő;

M.all.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (2)

Page 42: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

42

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.Adat := E;

Új.Következő := M.Következő;

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (3)

Page 43: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

43

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.Adat := E;

Új.Következő := M.Következő;

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (4)

aggregátum?

Page 44: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

44

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.all := ( E, M.Következő );

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (5)

Page 45: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

45

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.all := ( E, M.Következő );

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (6)

allokálás és inicializálás egyben?

Page 46: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

46

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs ' ( E, M.Következő );

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (7)

Page 47: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

47

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs ' ( E, M.Következő );

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (8)

Page 48: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

48

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató := new Csúcs ' ( E, M.Következő );

begin

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (9)

Page 49: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

49

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató := new Csúcs ' ( E, M.Következő );

begin

M.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (10)

Page 50: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

50

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

begin

M.Következő := new Csúcs ' ( E, M.Következő );

end Mögé_Beszúr;

Láncolt adatszerkezet használata (11)

Page 51: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

51

-- előfeltétel: M /= null

procedure Mögé_Beszúr ( M: in out Mutató; E: in Elem ) is

Új: Mutató;

begin

Új := new Csúcs;

Új.all.Adat := E;

Új.all.Következő := M.all.Következő;

M.all.Következő := Új;

end Mögé_Beszúr;

Láncolt adatszerkezet használata (12)

Page 52: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

52

Bizonyos esetekben az all opcionális

A mutatott objektum egy komponensére történő hivatkozáskor elhagyható

function F ( A, B: Integer ) return Mutató;P: Mutató := new Csúcs; S: PString := new String(1..5);

P.all.Adat + 1 P.Adat + 1F(X,Y).all.Adat + 1 F(X,Y).Adat + 1S.all(1) := 'a'; S(1) := 'a';

Akkor szokás használni, ha az egész hivatkozott objektummal csinálunk valamitif F(X,Y).all /= P.all then Put(S.all); end if;

Page 53: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

53

Sor típus láncolt ábrázolással

generictype Elem is private;

package Sorok istype Sor is limited private;procedure Betesz ( S: in out Sor; E: in Elem );procedure Kivesz ( S: in out Sor; E: out Elem );…

private…

end Sorok;

fejelem nélküli

egyszeresen láncolt

listával

Page 54: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

54

Reprezentáció

privatetype Csúcs;type Mutató is access Csúcs;type Csúcs is record

Adat: Elem; Következő: Mutató;

end record;type Sor is record

Eleje, Vége: Mutató := null; end record;

Page 55: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

55

Implementáció (Betesz)

package body Sorok isprocedure Betesz ( S: in out Sor; E: in Elem ) is

Új: Mutató := new Csúcs ' (E,null);begin

if S.Vége = null thenS := (Új, Új);

elseS.Vége.Következő := Új;S.Vége := Új;

end if;end Betesz;…

end Sorok;

Page 56: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

56

Implementáció (Kivesz)

procedure Kivesz ( S: in out Sor; E: out Elem ) isbegin

if S.Eleje = null then raise Üres_Sor;else

E := S.Eleje.Adat;if S.Eleje = S.Vége then

S := (null, null);else

S.Eleje := S.Eleje.Következő;end if;

end if;end Kivesz;

Page 57: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

57

Memóriaszivárgás: felszabadítás kell!

with Ada.Unchecked_Deallocation;

package body Sorok is

procedure Felszabadít is

new Ada.Unchecked_Deallocation(Csúcs, Mutató);

procedure Kivesz ( S: in out Sor; E: out Elem ) is …

end Sorok;

Page 58: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

58

Implementáció (Kivesz) javítva

procedure Kivesz ( S: in out Sor; E: out Elem ) isRégi: Mutató := S.Eleje;

beginif Régi = null then raise Üres_Sor;else E := Régi.Adat;

if S.Eleje = S.Vége then S := (null, null);else S.Eleje := S.Eleje.Következő;end if;Felszabadít(Régi);

end if;end Kivesz;

Page 59: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

59

Használjuk a Sor típust

with Sorok;procedure A is

package Int_Sorok is new Sorok(Integer);procedure B is

S: Int_Sorok.Sor;begin

Int_Sorok.Betesz(S,1);end B;

beginB;…

end A;Nem szabadul fel a

sort alkotó lista

Page 60: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

60

Memóriaszivárgás

with Sorok;procedure A is

package Int_Sorok is new Sorok(Integer);procedure B is

S: Int_Sorok.Sor;begin

Int_Sorok.Betesz(S,1);end B;

beginB; B; B; B; B; B; B; B; B; B; B; B; B; B;…

end A;

Page 61: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

61

Mi történik?

A sor objektumok a stack-en jönnek létre A sor elemei a heap-en allokáltak Amikor a sor objektum megszűnik

(automatikusan), az elemek nem szabadulnak fel Megoldás

– Felszámoló eljárást írni, és azt ilyenkor meghívni– C++: a sor destruktorában felszabadítani– Ada 95: Controlled típust használni

Page 62: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

62

Destruktor az Adában

with Ada.Finalization; use Ada.Finalization;generic

type Elem is private;package Sorok is

type Sor is new Limited_Controlled with private;procedure Finalize ( S: in out Sor );procedure Betesz ( S: in out Sor; E: in Elem );procedure Kivesz ( S: in out Sor; E: out Elem );…

private…

end Sorok;

Page 63: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

63

Reprezentáció

privatetype Csúcs;type Mutató is access Csúcs;type Csúcs is record

Adat: Elem; Következő: Mutató;

end record;type Sor is new Limited_Controlled with record

Eleje, Vége: Mutató := null; end record;

Page 64: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

64

A Limited_Controlled típus

Jelölt (tagged) típus– Újabb komponensekkel bővíthető rekord típus– Az OOP támogatásához (pl. dinamikus kötés)

A Sor típus ennek egy leszármazottja (new) Definiál konstruktort és destruktort, amelyeket a

leszármazott felüldefiniálhat– A konstruktor és a destruktor automatikusan lefut

létrehozáskor, illetve felszámoláskor

type Limited_Controlled is abstract tagged limited private;procedure Initialize (Object : in out Limited_Controlled);procedure Finalize (Object : in out Limited_Controlled);

Page 65: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

65

Implementáció (Finalize)

procedure Finalize ( S: in out Sor ) is

P: Mutató;

begin

while S.Eleje /= null loop

P := S.Eleje;

S.Eleje := S.Eleje.Következő;

Felszabadít(P);

end loop;

end Finalize;

Page 66: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

66

Implementáció (visszatérés)

procedure Betesz ( S: in out Sor; E: in Elem ) isÚj: Mutató := new Csúcs ' (E,null);

beginif S.Vége = null then S.Eleje := Új; else S.Vége.Következõ := Új; end if;S.Vége := Új;

end Betesz;

procedure Kivesz ( S: in out Sor; E: out Elem ) isRégi: Mutató := S.Eleje;

beginif Régi = null then raise Üres_Sor; -- ha üres a sorelse E := Régi.Adat;

if S.Eleje = S.Vége then S.Vége := null; end if; -- ha egyelemű volt

S.Eleje := S.Eleje.Következõ; -- itt csatolom kiFelszabadít(Régi);

end if;end Kivesz;

Page 67: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

67

A Controlled típus

Olyan, mint a Limited_Controlled De nem korlátozott típus A konstruktor és a destruktor mellett definiál

értékadáskor automatikusan lefutó műveletet– Ez a primitív művelet is felüldefiniálható– Olyasmi, mint a C++ értékadó operátor felüldefiniálása– Saját értékadási stratégia (shallow/deep copy)– Szokás az = operátort is felüldefiniálni vele együtt

procedure Adjust (Object : in out Controlled);

Page 68: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

68

Aljas mutatók

Olyan objektumra mutat, amelyet nem a heap-en hoztunk létre (Ada 95)

Az aliased és az all kulcsszavak kellenek Az Access attribútum „cím” lekérdezésére való,

minden típushoz használható

type P is access all Integer;N: aliased Integer := 1;X: P := N ' Access;

Az X.all egy alias lesz az N-hez

Page 69: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

69

Ilyesmi a C++ nyelvben

void f()

{

int n = 1;

int& r = n;

int* p = &n; // ez hasonlít a leginkább

}

Page 70: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

70

Borzasztó veszélyes

int *f ( int p ) {

int n = p;

return &n;

}

int main() {

int i = *f(3); // illegális memóriahivatkozás

}

Page 71: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

71

Az Ada szigorúbb, biztonságosabb

procedure A istype P is access all Integer;procedure B ( X: out P ) is

N: aliased Integer := 1;begin

X := N’Access;end B;X: P;

beginB(X);

end;

Fordítási hiba

Page 72: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

72

Élettartam ellenőrzése

X := N’Access;

Csak akkor helyes, ha az N objektum legalább ugyanannyi ideig fennmarad, mint az X típusa.

Az 'Access elérhetőségi ellenőrzést is végez, hogy a mutatott objektum élettartama legalább akkora-e, mint a mutató típusának hatásköre.

Megkerülni az ellenőrzést: 'Unchecked_Access

Page 73: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

73

Alprogramra mutató típus

procedure A ( N: in Integer ) is … begin … end A;type P is access procedure ( N: in Integer );X: P := A’Access;

... X.all(3); ... X(3); ...

void a ( int n ) { … }void (*x) (int) = a;

… (*x)(3); … x(3); ...

Ada 95

Page 74: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

74

Alprogrammal való paraméterezés

Sablon

generic

with function F ( A: Float ) return Float;

function Integrál ( Alsó, Felső, Lépés: Float ) return Float;

Alprogramra mutató típus

type F_Mutató is access function ( A: Float ) return Float;

function Integrál ( F: F_Mutató; Alsó, Felső, Lépés: Float ) return

Float;

Page 75: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

75

Eltérő megvalósítás

Az alprogramra mutató típus használatával csak könyvtári szinten megvalósított alprogramok adhatók át

Sablon esetén nincs ilyen megkötés– Viheti magával a környezetét– Ez jobban hasonlít a lezárt (closure) átadására,

lásd pl. Modula-3

Page 76: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

76

Sablon a sablonban

generictype Elem is private;

package Sorok istype Sor is new Limited_Controlled with private;…generic

with procedure Feladat ( E: in Elem );procedure Iterál ( S: in Sor );

private…

end Sorok; belső iterátor

Page 77: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

77

Implementáció (Iterál)

package body Sorok is…procedure Iterál ( S: in Sor ) is

P: Mutató := S.Eleje;begin

while P /= null loopFeladat( P.Adat );P := P.Következő;

end loop;end Iterál;

end Sorok;

Page 78: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

78

Összegzés

with Int_Sorok; use Int_Sorok;function Összeg ( S: Sor ) return Integer is

N: Integer := 0;procedure Hozzáad ( E: in Integer ) is begin N := N + E; end;procedure Összegez is new Iterál(Hozzáad);

beginÖsszegez(S);return N;

end Összeg;

with Sorok;package Int_Sorok is new Sorok(Integer);

Controlled leszármazottja

csak könyvtári szintű lehet

Page 79: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

Appendix

Page 80: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

80

type Tömb is array(1 .. 10) of Integer;

X: aliased Tömb;

X'Access --OK

X(1)'Access -- hibás kifejezés

type A_Tömb is array(1..10) of aliased Integer;

Y: A_Tömb;

Y(1)'Access --OK

Y'Access -- hibás kifejezés

Z: aliased A_Tömb;

Z'Access és Z(1)'Access is helyes

Page 81: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

81

type Rekord is record

A: aliased Integer;

B: Integer;

end record;

R1: aliased Rekord;

R2: Rekord;

R1.A'Access R2.A'Access -- helyes

R1.B'Access R2.B'Access -- helytelen

R1'Access -- helyes

R2'Access -- helytelen

Page 82: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

82

Konverzió két mutató típusra

type P is access Integer;type Q is access all Integer;X: P := new Integer’(3);Y: Q := Q(X);

type R is access all Integer;Z: R := Y.all’Access;

Az ‘Access attribútum tetszőleges típushoz jó

Page 83: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

83

procedure Program is

type P is access all Integer;

X: P;

procedure Értékadás is

I: aliased Integer := 0;

begin

X := I'Access; -- hibás értékadás, mert I az eljárás

-- után megszűnik, míg az X típusa nem

end Értékadás;

begin

Értékadás;

X.all := X.all + 1; -- itt lenne a nagy gond

end Program;

Page 84: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

84

procedure Program is

type P is access all Integer;

X: P;

procedure Értékadás is

type Q is access Integer;

Y: Q := new Integer’(0);

begin

X := Y.all'Access; -- hibás értékadás

end Értékadás;

begin

Értékadás;

X.all := X.all + 1; -- itt lenne a nagy gond

end Program;

Page 85: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

85

’Unchecked_Access

Vannak szituációk, ahol kényelmetlen az ellenőrzés

Kiskapu: az élettartam ellenőrzése ellen Nagyon veszélyes, mert ilyenkor a programozó

felelősége az, hogy ne legyen baj A fordító elfogadja az előző programokat, ha az

Unchecked_Access attribútumot használjuk A program működése azonban definiálatlan

Page 86: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

86

procedure A istype P is access all Integer;procedure B is

N: aliased Integer;type Q is access all Dátum;X: P := N'Access; -- ez hibásY: Q := N'Access; -- ez jóZ: P := N'Unchecked_Access; -- ez is!

begin...

end B;begin

...end A;

Page 87: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

87

procedure A istype P is access all Integer;W: P;procedure B is

N: aliased Integer;type Q is access all Dátum;X: P := N'Access; -- ez hibásY: Q := N'Access; -- ez jóZ: P := N'Unchecked_Access; -- ez is!

beginW := Z;

end B;begin

B; -- W.all definiálatlanend A;

Page 88: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

88

constant

„Nem változhat az értéke”

Szerepelhet:– Mutató deklarációjában– Mutató típus definíciójában

Page 89: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

89

Konstans mutató

type P is access Integer;

X: constant P := new Integer;

X.all := 5;

X := new Integer;

X := null;

Page 90: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

90

Konstansra is mutatható típus

type P is access constant Integer;X: P;

Az X-en keresztül nem módosítható a mutatott objektum

Maga az X módosítható (másik objektumra állítható)– hacsak nem tesszük konstanssá az X-et is...

Az X mutathat konstans objektumra is

Page 91: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

91

constant az all helyett

Nem csak dinamikusan létrehozott objektumra mutathat

type P is access constant Integer;

N: aliased Integer;

X: P := N’Access;

Page 92: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

92

constant az all helyett

Nem csak dinamikusan létrehozott objektumra mutathat

type P is access constant Integer;

N: aliased constant Integer :=3;

X: P := N’Access;

Page 93: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

93

constant az all helyett

Nem csak dinamikusan létrehozott objektumra mutathat

DE:

type P is access all Integer;

N: aliased constant Integer :=3;

X: P := N’Access;

Page 94: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

94

„konstans” hozzáférés

type P is access constant Integer;

N: aliased constant Integer := 42;

X: P := N’Access;

X.all := 33; -- hibát okozna, helytelen

Page 95: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

95

„konstans” hozzáférés

type P is access constant Integer;

N: aliased Integer := 42;

X: P := N’Access;

X.all := 33; -- helytelen

Page 96: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

96

type PKonst_int is access constant Integer;

type PInt is access all Integer; P: PKonst_int; Q: PInt; I: aliased Integer; K: aliased constant Integer := 20;-- a következő értékadások helyesek: P := K'Access; P := I'Access; Q := I'Access; Q.all := 29; P := new Integer'(0);-- a következő értékadások pedig helytelenek: P.all := 1; Q := K'Access; P := new Integer;

Page 97: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

97

type PKonst_Int is access constant Integer;type PInt is access all Integer;I: aliased Integer;K: aliased constant Integer := 20;P: PKonst_Int;Q: PInt;KP: constant PKonst_int := K’Access;KQ: constant PInt := I'Access;-- a következő értékadás helyes:KQ.all := 1;-- a következő értékadások hibásak: KP := new Integer'(100);KQ := new Integer'(200);KP.all := 10;

A mutató is lehet konstans

Page 98: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

98

Példák:

type Dátum is record

Év, Hónap, Nap: Integer;

end record;

type P1 is access Dátum;

type P is access all Dátum;

D1, D2: P;

U: aliased Dátum;

D1 := U'Access;

D1.all := (1997,2,2); -- a D1.Nap, illetve az U.Nap ugyanaz

Page 99: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

99

type P is access constant Dátum; -- read-only elérést ad

D: P; -- most ez konstans lesz abban az értelemben, hogy:

D := U'Access; -- megengedett,

U.Nap := 3; -- ez is,

D.Nap := 2; -- ez hibás, de a következő nem:

put(D.Nap); Megengedett viszont az is, hogy

D := new Dátum'(1999,2,2); Ha az U-t akarjuk konstanssá tenni, akkor azt kell írni, hogy:

U: aliased constant Dátum := (...);

Page 100: 8. el őadás Dinamikus mem óriakezelés. Mutatók. Láncolt adatszerkezetek

100

access alprogram paraméter

procedure A ( X: access Integer ) is ...

in módnak felel meg Az aktuális paraméter valamilyen Integer-re

mutató típusba kell tartozzon A formális paraméter sosem null

– A futtató rendszer ellenőrzi, hogy az aktuális ne legyen az

– A programozónak nem kell ezzel foglalkozni Korlátozott a paraméter

(nincs rá értékadás és egyenlőségvizsgálat)