- Динамикалық жадымен жұмыс істеуге арналған процедуралар мен функциялар
Динамикалық жадымен жұмыс істеуге арналған тағы бір қатар процедуралар мен функциялармен танысалық.
ADDR функциясы. Аргумент адресі сақталған POINTER типті көрсеткіштің нәтижесін қайтарады.
ADDR (X)
Мұнда Х – программаның кез-келген объекті(кез-келген айнымалының, процедураның, функцияның атауы). Қайтарылатын адрес кез-келген типтегі көрсеткішпен үйлесімді. Осындай нәтижені @ операциясы да қайтарады.
CSEG функциясы. Микропроцессордің СS регистрінде сақталынған мәнді қайтарады (программаның жұмысы басында СS регистрінде программа кодының басы сақталынады). Шақырылуы: СSEG
WORD типіндегі сөзді қайтарады.
DISPOSE процедурасы. Үймеге динамикалық жадының бұдан бұрын типтендірілген көрсеткішке бөлінген фрагментті қайтарады. Шақырылуы: DISPOSE (TP)
Мұнда ТР – типтендірілген көрсеткіш . Процедура босатылып қойған фрагмет үшін қайта шақырылатын болса программа орындалу кезінде қателік туындайды.
DSEG функциясы.Микропроцессордың DS регистрінде сақталған мәнді қайтарады(DS регистрінде программа жұмысының басында программа берілгендерінің бастамасының сегменті бар болады). Шақырылуы:
DSEG
Нәтиже WORD типті сөзде қайтарылады.
MAXAVAIL функциясы. Үйменің ең үлкен үздіксіз бөлігінің көлемін байт бірлігінде қайтарады. Шақырылуы:
MAXAVAIL
Нәтиже LONGINT типті болады. NEW жәнеGETMEM процедураларын бір шақыруда осы функцияның қайтаратын мәнінен артық жады иеленуге болмайды.
MEMAVAIL функциясы. Үйменің жжалпы бос кеңестігін байт өлшемінде қайтарады. Шақырылуы:
MEMAVAIL
Нәтиже LONGINT типті.
OFS функциясы. Көрсетілген объекттің адресінің жылжуына иеWORD типті мәнді қайтарады. Шақырылуы:
OFS(X)
Мұнда Х – кез-келген типтегі өрнек, немесе процедура атауы.
PTRфункциясы. Берілген сегмент SEG және жылжу OFS бойынша POINTER типті мән қайтарады. Шақырылуы:
PTR(SEG, OFS)
Мұнда SEG – сегмент сақталғанWORD типіндегі өрнек;
OFS – жылжу сақталғанWORD типіндегі өрнек.
- Үйме администраторы
Айтылып кеткеніндей, үйме администраторы – пайдаланушы программасының үймемен өзара әрекетін қамтамасыз ететін қызметші ішкі программа. Үйме администраторы NEW, GETMEM, DISPOSE, FREEMEM, т.б. процедуралардың сұранысын өңдейді және HEAPРTR, FREELIST көрсеткіштерінің мәнін өзгертеді. HEAPРTR көрсеткішінде үйменің бос бөлігінің төменгі шекара адресі сақталады. Ал, FREELIST көрсеткішінде бос блоктың сипаттаушысының адресі сақталады. SYSTEM модулінде FREELIST көрсеткіші POINTER ретінде сипатталған, алайда, іс-жүзінде ол берілгендердің келесі құрылымына нұсқайды:
Type
PFreeRec = ^ TFreeRec;
TFreeRec record
Next : pointer;
Size : pointer;
End;
Бұл тізімдік қрылым HEAPPTR шекарасынан төмен орналасқан жадының барлық бос блоктарын сипаттауға арналған. Блоктардың пайда болуы кезекпен NEW-DISPOSE не GETMEM-FREEMEM процедураларын кездейсоқ қолданудан болады. (Үйменің «ұяшықтық» құрылымы). PFREEREC жазбасындағы NEXT өрісі тізім бойынша келесі үйменің бос блогын немесе егер тізімде соңғы болса, онда HEAPEND-ке сәйкес келетін адресті өзінде сақтайды. SIZE өрісі нормал емес бос блоктың ұзындығын немесе егер,HEAPРTR-гі адрестен төмен бос блок жоқ болса, онда 0 мәніне ие болады. Нормал емес ұзындық былай анықталады:осы өрістің жоғарғы (старший) сөзінде бос параграфтардың шамасы сақталады. Ал, кішісінде – 0…15 диапазонындағы бос байттар көлемі сақталады. Келесі функция SIZE өрісінің мәнін бос блоктың нақты (іс-жүзіндегі) ұзындығына түрлендіреді:
Function BlbckSize(Size: pointer): Longint;
{Функция преобразует ненормализованную длину свободного блока в байты}
type
PtrRec = record
Lo, Hi : word
end;
var
LengthBlock: Longint;
begin
BlockSize := Longint(PtrRec(Size).Hi)*16 + PtrRec(Size).Lo
end;
Программаны іске қосқан соң HEAPPTR және FREELIST көрсеткіштерінде үйме басына сәйкес келетін адрес (екеуінде де) сақталады(бұл адрес HEAPORG көрсеткішінде сақталынады). Үйменің бірінші 8 байтында TFREEREC типті жазба сақталады(NEXT өрісінде HEAPEND мәнімен сәйкес келетін адрес, ал SIZE өрісінде 0 бар болады, бұл динамикалық жадыда “ұяшықтар” жоқ екендігінің қосымша белгісі). Үймемен жұмыс істеу барысында HEAPPTR көрсеткішіндегі адрестен (шекарадан) төмен жерде кемінде бір бос блок пайда болмайынша HEAPPTRмен FREELIST көрсеткіштері бірдей мәнге ие бола береді. Пайда болған жағдайда FREELIST көрсеткіші осы блоктың басына нұсқайды, ал босатылған блоктың бірінші 8 байтында жазбасы орналастырылады. FREELIST тізімінің басы ретінде пайдаланып, пайдаланушының программасы әрдайым барлық бос блоктардың тізімін қарап шыға алады және қажет болса оны модификациялай алады.
Баяндалған бұл механизмүйме администраторымен жұмыс істеуге байланысты бір кемшілікті тудырады: администратор кез-келген босатылған блокқа осы блоктың сипаттаушысын орналастыруы керек, ал бұл блоктың ұзындығы 8 байттан кем болмауы керек дегенді білдіреді. Үйме администраторыәрдайым жадыны өлшемі 8 байтқа(TFREEREC жазбасының көлеміне бөлінетін) бөлінетін блок ретінде (сұрағандарға) ажыратады. Егер программа 1 байт сұраса да, администратор оған іс-жүзінде 8 байт ажыратады. Сол сияқты 2,3,…8 байт сұралған жағдайлардың барлығында да 8 байттан ажыратылады. Ал, 9 байт сұралған жағдайда 16 байтты блок ажыратылады. Динамикалық жадыны үнемдегіміз келсе, бұл жағдайды ескеруіміз керек.
Егер NEW не GETMEM функцияларын кезекті рет шақырған кезде администратор үймеде қажетті бос блокты таба алмаса, ол HEAPERROR айнымалысында сақталған адрестегі функцияны шақырады. Бұл функция келесі процедуралық типке сәйкес келеді:
Type
HeapErrorFun = function (Size : word): integer;
Мұнда Size – ол үшін бос динамикалық жады жоқ болған айнымалының көлемі. Стандартты функция (адресі программаны іске қосқан кезде HEAPERROR айнымалысында сақталатын) 0 мәнін қайтарады, бұл программаны 203 кодты(203 Heap overflow error-Үйменің толып кеткен) қателік бойынша программаның тоқтатылуына әкеледі. Бұл функцияны қайтаанықтап, программа тоқтатылуының алдын алуға болады. Бұл үшін өз функциямызды жазып, оның адресін HEAPERROR көрсеткішіне орналастыру керек. Мысалы:
Function HeapFunc(Size: Word): Integer; far;
begin
HeapFunc := 1 end;
begin {Негізгі программа}
HeapError := @HeapFunc;
end.
Айта кетейік, HEAPERRORFUN типті функция динамикалық жадыдан орын сұрау қанағаттандырылмаған жағдайда ғана шақырылады. Ол 3 мәннің бірін қатаруы мүмкін:
0 – программа жұмысын тоқтату;
1 – сәйкес көрсеткішке NIL мәнін меншіктеп, программа жұмысын жалғастыра беру;
2 – жады бөлуді қайталау; әрине, бұл жағдайда HEAPERRORFUN типті функцияның ішінде керекті өлшемдегі жадыны босату қажет.