Процедури GetMem и FreeMem - програмиране от

И понякога не искате да разпределяте памет по начина, по който го прави New. Може да се наложи да разпределите повече или по-малко памет, отколкото New прави по подразбиране, или може просто да не знаете колко памет трябва да използвате, преди да започне изпълнението. Borland Pascal извършва това разпределение с помощта на процедурата GetMem.

Процедурата GetMem приема два параметъра: променливата на указателя, за която искате да разпределите памет, и броя байтове за разпределяне.

Динамично разпределение на памет за низ

Да кажем, например, че имате приложение, което чете 1000 реда от файл и ги записва в динамична памет. Не знаете колко дълъг ще бъде всеки от тези низове, така че ще трябва да декларирате тип низ, който е толкова голям, колкото максималния възможен низ. Ако приемем, че не всички низове имат максимална дължина, тогава ще губите памет.

За да разрешите този проблем, можете да прочетете всеки ред в буфер, след което да разпределите толкова памет, колкото е необходимо за действителните данни в реда. Пример за това е показан по-долу:

Вместо разпределението за 256K низове (256 знака на низ 1000 пъти), вие сте разпределили 4K (4 байта на указател 1000 пъти), плюс количеството действително зает текст.

Освобождаване на разпределената памет

Подобно на начина, по който искате да освободите памет, разпределена с New, трябва да освободите памет, разпределена с GetMem. Това може да стане с помощта на процедурата FreeMem. Точно както всяко ново повикване трябва да бъде съпоставено с извикване на Dispose, всяко повикване на GetMem трябва да бъде съпоставено с извикване на FreeMem.

Подобно на GetMem, процедурата FreeMemприема два параметъра: променливата за освобождаване и количеството памет за освобождаване. Важно е количеството освободена памет да съвпада точно с количеството разпределена памет. New и Dispose винаги знаят колко байта да заделят или освобождават въз основа на типа на указателя. Но в случая на GetMem и FreeMem количеството разпределена памет е изцяло под ваш контрол.

Ако освободите по-малко байтове, отколкото са били разпределени, тогава останалите байтове се губят (възникват "течове" на купчина). Ако освободите повече байтове, отколкото сте разпределили, може да освободите паметта, разпределена за друга променлива, което може да доведе до повреда на данните. В защитен режим освобождаването на повече памет от разпределената ще доведе до грешка при нарушение на сигурността (GP).

Да предположим, например, че ще разпределите памет за един или повече записи на данни от тип TCheck:

Всеки запис от тип TCheck е 50 байта, така че ако имате променлива ThisCheck от тип PCheck, можете да разпределите динамичен запис по следния начин:

и по-късно го освободете с повикване:

Използване на SizeOfс процедурата GetMem

Но не е достатъчно да се уверите, че разпределяте и освобождавате едно и също количество памет всеки път. Трябва да се уверите, че е разпределено правилното количество памет. Да предположим, че сте променили дефиницията на TCheck. Например, ако сте предефинирали TCheck.Payee да бъде низ от 50 знака вместо такъв от 39 знака, няма да можете да получите и освободите достатъчно памет. Най-безопасно е да използвате функцията SizeOf в програмата,например:

Това не само гарантира, че разпределяте и освобождавате една и съща сума, но гарантира, че когато типът се преоразмери, вашиятпрограмата пак ще разпредели необходимата памет.

Проверка на количеството налична хийп памет

Borland Pascal дефинира две функции, които връщат важна информация за динамично разпределена област на паметта: MemAvail и MaxAvail.

Функцията MemAvail връща общия брой байтове, налични за разпределяне на паметта. Преди да разпределите голямо количество хийп памет, добра идея е да се уверите, че това количество памет е налично.

Функцията MaxAvail връща размера на най-големия наличен блок от непрекъсната памет в купчината. Първоначално, когато програмата стартира, MaxAvail е равен на MemAvail, тъй като цялото пространство на купчината е налично и непрекъснато. След разпределяне на множество блокове памет, пространството в купчината вероятно ще стане фрагментирано. Това означава, че има разпределени блокове между частите на свободното пространство. Функцията MaxAvail връща размера на най-големия свободен блок.