Часто приходиться иметь дело с массивами, длина которых не поддерживается стандартным array of . Мне приходилось иметь дело с массивом данных содержащих более тридцами миллионов записей, каждая из которых была record агрегирующий в себе 7 простых типов данных. При этом вы хотите обрадовать массив не простых типов данных Integer или Double, а массив данных, которые вы объявили при помощи конструкций TMyRecord = Record .. end; или TMyClass = class .. end;.. Ваше Желание может быть объяснено простым желанием работать с удобной структурой данных, а не выделять множество массивов простых типов данных и потом имеь куцу проблем с областью видимости и передачи их как формальных параметров в функции и процедуры. При их размещении в памяти возникает ошибка
—————————
Debugger Exception Notification
—————————
raised exception class ERangeError with message ‘Range check error’.
—————————
Break Continue Help
Или же
—————————
Debugger Exception Notification
—————————
raised exception class EOutOfMemory with message ‘Out of memory’.
—————————
Break Continue Help
В первом случае в принципе не возможно задать массив такой длины, а во втором Объем памяти ,который запрашивает программа может превышать доступные на даны момент ресурсы компьютера.
Для решения проблемы воспользуемся функцией
function GetMem ( var StoragePointer : Pointer; StorageSize : Integer ) ;
которая описана в модуле (Юните, Unit) System;
Официальные источники дают следующие описание данной процедуры:
Процедура GetMem пытается получить указанные в StorageSize байт памяти, сохраняя указатель на память в StoragePointer. Если при распределении произошли сбои, то вызывается исключение EOutOfMemory. Память не всегда инициализируется.
Таким образом, для того, что бы воспользоваться этой функцией необходимо знать количество элементов (объектов), которое мы хотим выделить и количество байтов (размер каждого элемента). При этом StoragePointer – должен быть указателем а StorageSize – содержать длину оттельного объекта типа TMyRecord. При объявлении TMyRecord обязательно объявляйте его packed record. Например,
TMyRecord = packed Record .. end;
Директива packed поможет менеджеру памяти наиболее эффективно расположить в памяти каждую запись. Так же воздержитесь от использования в record использования данных не фиксированной длины, например, String вместо него используйте String[255] или любой другой нужной вам длины.
Длину отдельного объекта можно определить при помощи функции SizeOf.
Официальные источники дают следующие описание данной процедуры:
Функция SizeOf возвращает занимаемый размер (в байтах) переменной (Variable) или типа (Type).
То есть для того что бы узнать длину класса TMyRecord необходимо вызвать SizeOf(TMyRecord), при этом следует помнить, что SizeOf(TMyRecord) один раз вычисляет длину класса в байтах и при повторном вызове не будет повторно пересчитывать его длину, так что вызовы SizeOf(TMyRecord) не могут серьезно повлиять на время выполнения программы.
Так что перед тем как начать заполнять данными область памяти необходимо подсчитать количество элементов, которое вам понадобиться. Даже если для этого понадобиться дважды прочитать текстовый файл.
var
F: TextFile ;
lValue: PMyRecord;
p: pointer;
lRowsCount: Integer;
begin
try
Result:= True;
AssignFile(F, APath);
lRowsCount:= 1;
Reset(F);
while not Eof(F) do
begin
Readln(F,str);
inc(lRowsCount);
end;
lRowsCount:= lRowsCount;
GetMem(p, lRowsCount*SizeOf(TMyRecord));
Reset(F);
APointer:= p;
lValue:= p;
while not Eof(F) do
begin
// считываем даные в массив
str:=”;
Readln(F, lValue^.EdgeGroupID, lValue^.Day, str);
lValue:= pointer(integer(lValue) + SizeOf(TJame));
end;
finally
CloseFile(F);
end;
end;
на соответствующий типа записи. Например, PMyRecord = ^TMyRecord,
[...] [...]
Занимательно и полезно, а будет еще что-то из этой же серии?
Да уж. Думаю многие будут не согласны..
Всем привет! Я здесь новенький. Примите в вашу компанию?
Свобода слова на блоге – это всегда хорошо! Главное, чтобы общественности было что Вам сказать
Хм… Пока это у нас не сильно развито, так что придётся подождать.
Спасибочки, что просветили. Никогда бы не подумал
Премного благодарен. Прочитал с огромным интересом, и вообще полезный у Вас блог
Уважаемые, а нельзя оставлять комментарии по теме, а не разную глупость типа Спасибо за статью и т.д.
That saves me. Thkans for being so sensible!
Решил вам немного помочь и послал этот пост в социальные закладки