Программалау іі» пәні бойынша 050111 «Информатика»


Лекция 2 Динамикалық жадыны бөлу және босату



бет4/29
Дата14.06.2016
өлшемі2.7 Mb.
#135126
түріПрограмма
1   2   3   4   5   6   7   8   9   ...   29

Лекция 2

Динамикалық жадыны бөлу және босату

Жоспар:


1. Үйме. HEAPORG, HEAPEND, HEAPPTR көрсеткіштері

2. Көрсеткішті пайдалану

3. DISPOSE процедурасы

Әдебиеттер:


1.А.Г.Гольцев «Объектно-ориентированное программирование и его реализация в языке Паскаль», Москва-2005

2. В.В.Фараонов «Турбо Паскаль 7.0», Москва-2001

3. Электронный учебник: «Введение в объектно-ориентированное программирование», 2006
1. Үйме. HEAPORG, HEAPEND, HEAPPTR көрсеткіштері

Турбо Паскалда барлық динамикалық жады түгелімен үйме (куча)деп аталатын байттардың массиві ретінде қарастырылады. Үйме физикалық тұрғыдан жоғарғы(в старших адресах) адрестерде, программаның денесі орналасқан жады облысынан соң бірден басталады. Үйменің басы стандартты HEAPORG айнымалысында, ал соңы HEAPEND айнымалысында сақталады. Динамикалық жадының бос аймағының шекарасы HEAPPTR көрсеткішінде сақталады.

Кез-келген динамикалық орналастырылатын айнымалы үшін жады NEW процедурасы арқылы бөлінеді. Бұл процедураны шақыруда қолданылатын параметр – типтендірілген көрсеткіш болып табылады. Процедураны шақыру нәтижесінде көрсеткіш берілгендерді орналастыру қайсы динамикалық ұяшықтан басталатын болса сол динамикалық ұяшықтың адрестік мәнін қабылдайды. Мысалы:

var


i, j : ^integer;

r : ^real;

begin

new(i);


……..

end.
Осы программа бөлігі орындалған соң і көрсеткіші бұдан алдын үйменің көрсеткіші HEAPPTR ие болған мәнді қабылдайды, ал HEAPPTR болса өз мәнін 2-ге арттырады, integer типтің жадыдан алатын орны – 2 байт.

new(r);

операторы HEAPPTR көрсеткішін тағы да 6 байтқа жылжытады, өйткені real типі үшін 6 байт орын бөлінеді.



HeapEnd



Жүйелік облыс

Жоғарғы адрестер

Үйме



HeapPtr



HeapOrg



Программа

Жүйелік облыс

Кіші адрестер



ДК-ң жадысында үйменің орналасуы
2. Көрсеткішті пайдалану

Көрсеткіш қайсыбір мәнге ие болған соң, яғни нақты физикалық жады байтын көрсетіп тұрған соң, осы адреске кез-келген типі сәйкес келетін мәнді орналастыруға болады. Бұл үшін көрсеткішке тіркеп ^ белгісі қойылады. Мысалы:

i^ :=2; {і жады бөлігіне 2 мәні орналастырылды}

r^ :=2*pi {r жады бөлігіне 6.28 мәні орналастырылды}


Осылайша, көрсеткішке ^ белгісі тіркелсе ол адресте орналасқан мәнді білдіреді. Егер бұл белгі қойылмаса, онда көрсеткіш осы мән орналасқан адресті білдіреді.

Динамикалық орналасқан берілгендерді сәйкес типтің тұрақтылары ме айнымалылары қолданылатын жерлердің барлығында пайдалана беруге болады. Мысалы:


r^ := sqr(r^)+i^-17;

Ал, енді былай жазуға болмайды: r := sqr(r^)+i^-17;

Өйткені, r көрсеткішіне нақты мәнді беруге болмайды. Дәл осылайша

r^ := sqr(r);


деп жазуға болмайды. Өйткені r-ң мәні адрес болғандықтан оны квадраттауға болмайды.

Былай жазу да қате боп табылар еді. r^ := і;

Өйткені, r^ көрсетіп тұрған нақты мәндерге көрсеткіш мәнін, яғни адресті меншіктеуге болмайды.
3. DISPOSE процедурасы

Үймеден динамикалық жадыны тек алу ғана емес, кері қайтаруға да болады. Бұл үшін DISPOSE процедурасы қолданылады. Мысалы, dispose (r) ;

dispose (і) ; операторлары і және r көрсеткіштері үшін алдын бөлінген 8 байтты үймеге қайтарады, ал көрсеткіштер мәнсіз, бос қалады. Осы көрсеткіштерге операторды қайтара қолдану программа орындалу барысында қателік туғызады. Босаған көрсеткішті программист NIL сөзі арқылы белгілеп қоюына болады. Көрсеткіштердің біріне белгі қойылған не қойылмағандығын былай тексеруге болады:

const


p: ^real = NIL;

begin


…….

if p = NIL then

new(p);

…………


dispose (p);

p := NIL;

……….

end.
Көрсеткіштерді салыстырудың басқа амалдарына рұксат етілмеген.



Жоғарыда келтірілген программа бөлігі көрсеткішті бірмезгілде типтелген және NIL мәні меншіктелген константа ретінде жариялау әдісін көрсетеді. Айта кету керек, көрсеткіштің бастапқы мәні (айнымалылар бөлімінде жарияланған уақытта) кез-келген болуы мүмкін. NEW процедурасы арқылы немесе басқа жолмен мәні меншіктелмеген көрсеткіштерді пайдалану жүйе тарапынан қадағаланбайды, сондықтан қолайсыз жағдайлар туғызуы мүмкін.

NEW және DISPOSE процедураларын кезек-кезек қолдану жадының «ұяшықты» құрылымына әкеледі. Мәселе мынада, үймеге қатысты барлық амалдар үйме администраторы деп аталатын ерекше көмекшіпрограмманың басқаруымен орындалады. Ол автоматты түрде Турбо Паскальдің компоновщигі арқылы қосылады да үймедегі барлық бос фрагменттер есебін жүргізіп отырады. NEW процедурасын кезекті рет шақырған кезде осы көмекшіпрограмма берілген айнымалы сиятындай ең кіші бос фрагментті іздестіреді. Табылған фрагменттің басы көрсеткішке меншіктеледі, ал фрагмент толығымен не талап етілген бөлігі үйменің бос емес бөлігі ретінде белгіленіп қойылады.



Лекция 3

Динамикалық жадыны бөлу және босату.
Жоспар:

1. MARK және RELEASE процедуралары

2. Getmem және Freemem процедуралары

Әдебиеттер:


1.А.Г.Гольцев «Объектно-ориентированное программирование и его реализация в языке Паскаль», Москва-2005

2. В.В.Фараонов «Турбо Паскаль 7.0», Москва-2001

3. Электронный учебник: «Введение в объектно-ориентированное программирование», 2006
1. MARK және RELEASE процедуралары

Келесі мүмкіндік үйменің бүтін бір фрагментін босатудан тұрады. Осы мақсатпен динамикалық жадыны бөлу алдынан HEAPPTR көрсеткішінің ағымдағы мәні MARK процедурасының көмегімен айнымалы-көрсеткішке сақталынып қойылады. Енді кез-келген уақытта MARK процедурасы сақтап қойған адрестен бастап динамикалық жадының соңына дейін босатуға болады. Бұл үшін RELEASE процедурасы қолданылады. Мысалы:

var

p,p1,p2,p3,p4,p5 : integer;



begin

new(p1);


new(p2);

mark(p);


new(p3);

new(p4);


new(p5);

……….


release(p);

end.


Бұл мысалда MARK(P); процедурасы арқылы P көрсеткішіне HEAPPTR-ң ағымдағы мәні сақталынған, алайда айнымалы үшін жады бөлінбеді. RELEASE(P) процедурасын шақыру динамикалық жадының Р көрсеткішіндегі адрестен бастап үйменің аяғына дейін босатады. Келесі суретте NEW-DISPOSE және NEW-MARK-RELEASE процедураларының механизмі, сонымен бірге RELEASE(P) операторының орнына мысалы DISPOSE(Р3) қолданылған жағдай көрсетілген.





р1^




р1^




р1^




р2^




р2^




р2^

Mark(p1)

р3^

Dispose(p)

/////////////////

Release(p)

//////////////////

//////////////////

//////////////////

//////////////////

//////////////////





р4^




р3^







р5^




р4^







/////////////




р5^





2. Getmem және Freemem процедуралары

Біз білеміз, NEW процедурасының параметрі тек қана типтендірілген көрсеткіш бола алады. Типтендірілмеген көрсеткіштермен жұмыс істеу үшін мына процедуралар қолданылады:

GETMEM (P, SIZE) – жадыны бөлу; 

FREEMEM(P, SIZE) – жадыны босату.

Мұнда Р – типтендірілмеген көрсеткіш;

SIZE – талап етілген не босатылатын үйме бөлігінің байттық өлшемі.

GETMEM процедурасын бір шақыруда 65521 байтқа дейін динамикалық жадыны иелеуге болады.

GETMEM-FREEMEM процедураларын қолдану жалпы динамикалық жадымен жұмыс істеу сияқты, қарапайым ережені қатал сақтауды талап етеді: қанша көлемде жады иеленсе, сонша көлемде жадыны босату керек және қай адрестен бастап иеленген болса, сол адрестен бастап босатылады.

Типтендірілмеген көрсеткіштердің ендірілуі(стандартты Паскальда жоқ болатын) типтерді айқын емес түрлендіруге кең мүмкіндіктер ашады. Өкінішке орай, NEW және DISPOSE процедураларын корректсіз қолдану типтерді күтілмеген түрлендіруге әкелуі мүмкін. Айталық, мынадай программа бар болсын:

var


i,j : Integer; 

r : Real; 

begin

new(i); {i := HeapOrg; HeapPtr:= HeapOrg + 2}



j := i; {j := HeapOrg} 

j := 2;


dispose(i); {HeapPtr := HeapOrg} 

new(r); {r := HeapOrg; HeapPtr:= HeapOrg + 6}

r := pi; 

WriteLn(j) 

end.

Дисплей экранына не шығарылады? Бұл сұраққа жауап беру үшін HEAPPTR көрсеткішінің мәндерін бақылайық. Программа орындалу алдынан үйме басының адресі –HEAPORG-ке ие болған, бұл мән I көрсеткішіне ал, бұдан соң J көрсеткішіне беріледі. DISPOSE(I) орындалғаннан кейін үйме көрсеткіші қайтдан HEAPORG мәніне ие болды, осы адес NEW(R) процедурасындағы R көрсеткішіне беріледі. R адресі бойынша pi=3.14159 нақты саны орналастырылғаннан кейін, үйменің алғашқы 2 байтын осы санның ішкі көрінісінің бір бөлігі иелейді. Бұл кезде J-де әлі де HEAPORG адресі сақталынған, содықтан WRITELN(J^) операторы pi санының 2 байтын бүтін санның ішкі көрінісі деп түсінеді( өйткені J – INTEGER типті көрсеткіш) және 8578 мәнін көрсетеді.


Лекция 4

Көрсеткіштерді қолдану

Жоспар:


1. Берілгендер массивін орналастыру үшін динамикалық жадыны пайдалану

2. Матрица элементтерінің орташа мәнін есептеу мысалы





Достарыңызбен бөлісу:
1   2   3   4   5   6   7   8   9   ...   29




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет