TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

Процедуры GetMem и FreeMem 

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

             Процедура GetMem воспринимает два параметра: переменную-ука-
        затель, для которой вы хотите распределить память,  и число расп-
        ределяемых байт.

                    Динамическое выделение памяти для строки

             Пусть, например,  у вас есть прикладная  программа,  которая
        считывает 1000  строк из файла и записывает их в динамическую па-
        мять. Вы не знаете, насколько длинной будет каждая из этих строк,
        поэтому вам  потребуется  описать  строковый  тип такого размера,
        который будет соответствовать максимальной возможной строке. Если
        предположить, что  не  все строки имеют максимальную длину,  то у
        вас будет бесполезно использоваться память.

             Чтобы решить эту проблему, вы можете считать каждую строку в
        буфер, затем выделить столько памяти,  сколько требуется для фак-
        тических данных в строке. Пример этого показан ниже:

             type PString = ^String;

             var
               ReadBuffer: String;
               LinewRead: array[1..1000] of PString;


               TheFile: Text;
               LineNumber: Integer;

             begin
               Assign(TheFile, 'FOO.TXT');
               Reset(TheFile);
               for LineNumber := 1 to 1000 do
               begin
                 Readln(ReadBuffer);
                 GetMem(LinesRead[LineNumber], Length(ReadBuffer) + 1);
                 LinesRead[LineNumber]^ := ReadBuffer;
               end;
             end.

             Пример. 8.4 Динамическое распределение памяти для строки.

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

                         Освобождение выделенной памяти

             Аналогично тому,  как требуется освобождать память, выделен-
        ную с помощью New, вам нужно освобождать память, распределенную с
        помощью процедуры  GetMem.  Это можно сделать с помощью процедуры
        FreeMem. Аналогично тому, как каждому вызову New должен соответс-
        твовать парный  вызов  Dispose,  каждому  вызову процедуры GetMem
        должен соответствовать вызов FreeMem.

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

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

             Предположим, например,  что вы собираетесь  выделить  память
        для одной или более записей данных типа TCheck:

             type
               PCheck = ^ TCheck;
               TCheck = record
                   Amount: Real;
                   Mounth: 1..12;


                   Day: 1..31;
                   Year: 1990..2000;
                   Payee: string[39];
             end.

             Пример 8.5 Простой тип записи.

             Каждая запись типа TCheck занимает 50 байт,  поэтому, если у
        вас есть переменная ThisCheck типа PCheck, вы можете распределить
        динамическую запись следующим образом:

             GetMem(ThisGheck, 50);

        а позднее освободить ее с помощью вызова:

             FreeMem(ThisCheck, 50);

                Использование с процедурой GetMem функции SizeOf

             Однако убедиться, что вы каждый раз выделяете и освобождаете
        один и тот же объем памяти,  недостаточно.  Вы должны  обеспечить
        распределение правильного объема памяти. Предположим, вы изменили
        определение TCheck. Например, если вы переопределили TCheck.Payee
        как 50-символьную строку вместо 39-символьной,  то не сможете по-
        лучить и освобождать достаточно памяти.  Надежнее всего использо-
        вать в программе функцию SizeOf, например:

             GetMem(ThisCheck, SizeOf(TCheck));
                 .
                 .
                 .

             FreeMem(ThisCheck, SizeOf(TCheck));

             Это не только обеспечивает,  что вы выделяете и освобождаете
        один и  тот же объем,  но гарантирует,  что при изменении размера
        типа ваша программа все равно будет выделять нужную память.



Содержание

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz