Programozás alapjai 10. előadás Wagner György Általános Informatikai Tanszék
Programozás alapjai
Pointerek, dinamikus memóriakezelés A PC-s Pascal (is) az IBM PC memóriáját 4 fő részre osztja: – – – –
kódszegmens adatszegmens stackszegmens heap
Alapja: 1 byte: 0 - 255 2 byte: 0 - 65535 Ha ezt címek tárolására használjuk, akkor 2 byte-on (16 biten) csak 64 Kb címezhető meg. Programozás alapjai
Szegmensek Az Intel 80286 processor 16 bites. A 64 Kb kevés. Megoldás: – vegyünk 64 Kb-os lapokat – ezen belül 2 byte-tal pontosan lehet címezni – a 64 Kb-os lapokat számozzuk meg. Erre használjunk 4 bitet. 4 bit 0 - 15 között képes értékeket tárolni, ez tehát 16 lap. – 16 × 64 Kb = 1024 Kb = 1 Mb
Egy Dos számára ebből 640 Kb férhető hozzá. A lapokat nevezzük page-eknek vagy szegmenseknek. Ez a fajta címzés az ún. szegmenses címzés. Programozás alapjai
Szegmenses címzés (2) Ugyanazon szegmensen belüli címek közvetlenül címezhetők. Más szegmensben levő címek eléréséhez ún. szegmens regisztereket kell használni. Szegmens regiszterek: – – – –
CS: Code Segment Register DS: Data Segment Register SS: Stack Segment Register ES: Extra Segment Register Programozás alapjai
TP-FP memória kezelése Unitok használata esetén minden egyes Unitnak saját kódszegmense van. A főprogramnak úgyszintén saját kódszegmense van. => Az egyes modulok mérete nem haladhatja meg a 64 Kb-ot. Minden program 1 (!) adatszegmenssel rendelkezik. Az adatszegmensben a főprogram tipizált konstansai, változói és az egyes unit-ok Interface részében deklarált hasonló objektumai vannak. Az adatok tárolása itt statikus, azaz a változónak lefoglalt hely a program futásának kezdetétől annak végéig foglalt marad.
Programozás alapjai
TP-FP memória kezelése (2) Adattárolásra felhasználható még a stack és a heap. A stack-en csak közvetve lehet adatokat tárolni (lokális változók, értékszerint átadott paraméterek, …). A heap a programozó „kezére van bízva”. A TP-FP két standard függvénnyel rendelkezik: SEG ( ) OFS ( ) Programozás alapjai
TP-FP memória kezelése (3) A SEG ( ) azt a szegmens címet adja vissza, amelyben a paraméterként megadott változó található. Az OFS ( ) azt a szegmensen belüli címet (ún. eltolási cím vagy offset cím), amelyben a paraméterként megadott változó található. (A kezdőcímét…) (Példa program 4 különböző típusú (Word, String[5], Real, Char) változó egy-egy futáson közbeni szegmens és offszet címének kiírására. Szünetben megnézhető…) Programozás alapjai
TP-FP memória kezelése (4) Futásonként más és más íródhat ki. Pl.: Word : 68BB:003C String : 68BB:003E Real : 68BB:0044 Char : 68BB:004A A szegmens cím minden esetben megegyezik, mert mind az adatszegmensben van. A 20 bites cím (4+16) képzése: 68BB0 ⇐ (megszoroztuk hexa 10-zel) + 003C -------------------68BEC Programozás alapjai
TP-FP memória kezelése (5) A nem tipizált konstansok a kódszegmensben vannak, részesei az utasításnak. Ebből következik, hogy a nem tipizált konstansoknak NINCS (!) címük.
Programozás alapjai
Dinamikus változók Cél: olyan változók használata, amelyek a heap-en tárolódnak. Oka, hogy a heap nagy, egybefüggő, adattárolásra alkalmas memóriaterület. Egy nagy probléma van, hogy a programozónak kell az ott tárolt változót kezelgetnie. A változók egyik legfontosabb attributum-a címe. Vagyis a programozónak őriznie kell a heap-en tárolt változók címeit. Ehhez olyan változóra lesz szüksége, amely címet képes tárolni. Ezek a változók a pointerek (mutatók).
Programozás alapjai
Dinamikus változók (2) Egy változó akkor dinamikus, ha számára csak akkor foglalódik le a hely a memóriából, amikor a változót ténylegesen használjuk, majd utána ezt a memóriát fel lehet szabadítani. A foglaláshoz tudni kell, hány byte-ot kell lefoglalni. Ez a típustól függ (de ugye ezt már mindenki tudja is…) Megoldás: a pointer változónak is „tudnia kell”, milyen típusú változóra fog mutatni.
Programozás alapjai
Dinamikus változók (3) Szintaktika: Program Pr1; Var p : ^Integer; Begin New ( p ); p ^ := 100; WriteLn (’Az érték, amire p mutat:’, p ^); Dispose ( p ); End. Programozás alapjai
Dinamikus változók (4) Megjegyzés: mivel a pointer változó statikusan (!) tárolódik, ezért az egész csak akkor kifizetődő, ha ennél nagyobb, pl.: összetett adatszerkezetre mutat (célszerűen rekordra). New ( ): a paraméterként megadott pointerváltozóhoz hozzárendeli azt a memóriacímet, amelytől kezdve a dinamikus változó tárolásához elegendő memória áll rendelkezésre, majd lefoglalja a heap-ről ezt a memória területet.
(Szerencsére azt, hogy hol van szabad hely a heap-en, már nem a programozónak kell kikeresnie…) Dispose ( ): a p-ben tárolt címtől kezdve felszabadítja a heap-en a lefoglalt memória területet. Programozás alapjai
Dinamikus változók (5) Értékadás: p ^ := 100; és nem: p := 100;
Programozás alapjai
Dinamikus változók (6) Más hibalehetőség: Ugyanannak a pointerváltozónak kétszer vagy többször NEM SZABAD (!) egymásután memóriát foglalni a New ( ) -val anélkül hogy közben fel ne szabadítanánk, mert a Dispose ( )-zal csak a legutoljára lefoglalt memóriaterület szabadítható fel, a többi elveszik! Ellenőrizni kell, hogy a program futtatása előtt mennyi volt a szabad memória terület, majd ellenőrizni kell a program futása után is. Ha nem egyezik meg a két érték, akkor általában ez a baj... Programozás alapjai