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

  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 байт орын бөлінеді.

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

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

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^ көрсетіп тұрған нақты мәндерге көрсеткіш мәнін, яғни адресті меншіктеуге болмайды.

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

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

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

const

p: ^real = NIL;

begin

ifp = NIL then

new(p);

dispose (p);

p := NIL;

end.

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

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

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