Текущий архив: 2005.11.13;
Скачать: CL | DM;
Вниз
Динамический массив: ошибка компилятора? Найти похожие ветки
← →
Александр Слоб. (2005-10-19 06:51) [0]Добрый день!
Господа, столкнулся со следующей проблемой:
объявлен дин. массив, содержащий в себе другой дин. массив:
type
TCell = record
num: integer;
par: array of word;
end;
var
CellsArrDynamic: array of TCell;
При следующей его инициализации (например) всё проходит успешно (Task Manager Windows показывает, что выделилось несколько десятков Кб памяти):
for cycle:=0 to 10000 do
SetLength(CellsArrDynamic, Length(CellsArrDynamic) + 1 );
for cycle:=0 to 10000 do
SetLength(CellsArrDynamic[cycle].par, 1)
Но мне в процессе работы программы нужно было добавлять по одному элементу по мере необходимости.
И если мы напишем следующий код, то закончим выделением порядка 100 Мб памяти (!!!), ну или ошибкой "Out of Memory":
for cycle:=0 to 10000 do
begin
SetLength(CellsArrDynamic, Length(CellsArrDynamic) + 1 );
SetLength(CellsArrDynamic[cycle].par, 1)
end;
Разница лишь в том, что в первом случае инициализируем сначала весь массив, а затем все его подмассивы, а во втором это делаем по порядку.
Процедуры приведены в точности, как они есть в программе. Delphi 7.
Подскажите, в чём моя ошибка и как быть, если всё-таки необходимо добавлять по одному элементу в течение программы.
← →
MBo © (2005-10-19 07:36) [1]>всё-таки необходимо добавлять по одному элементу в течение программы
Все-таки нельзя так делать.
При увеличении массива на единицу вот что получается (упрощенно) - он не вмещается в старое место - менеджер памяти выделяет новый блок памяти, копирует туда данные, а старый когда-нибудь освободится. Однако освобожденные блоки - меньшего размера, чем требуется на каждом шаге цикла, и не могут использоваться, по крайней мере, до их слияния, которое неизвестно еще когда произойдет, тем более, что ты не даешь системе отдышаться, гоня свой цикл. Отсюда и непомерное потребление памяти.
При возможности предусмотреть размер массива - выделяй память в разумном количестве сразу. Ну займешь мегабайт - и все.
Если по мере работы массив весь заполняется - увеличь длину сразу на существенное количество - например, на 1000, или на четверть.
А может - тебе вообще TList подойдет - он примерно так и действует.
← →
alex_*** (2005-10-19 09:19) [2]что за привязанность к дин. массивам? не надоело ошибки выделения/освобождения памяти ловить? Закать все в объекты и в ObjectList
← →
evvcom © (2005-10-19 09:39) [3]Может я отстал от жизни, и в русском языке появилось много новых слов, но я не пойму значения слова "закать". И почему так категорично к дин. массивам? Где-то действительно удобен ObjectList, а где-то и дин. массив.
← →
alex_*** (2005-10-19 10:12) [4]закатать :) Когда списки вложенных списков/векторов то удобнее и нагляднее в объекты и в список объектов. А когда просто вектор чего-то и то и дин. массив подойдет. ИМХО.
← →
Александр Слоб. (2005-10-19 19:45) [5]МВо, блгодарю за ответ!
Да, действительно всё так - следует увеличивать массив сразу на большее число элементов. Работает прекрасно.
← →
Александр Слоб. (2005-10-19 19:54) [6]И в догонку ещё один интересный факт:
При объявлении статического массива - Delphi не выделяет память под его ячейки до первого обращения к ним. (по показаниям TaskManager, например).
Когда узнал это - очень удивился.
Если это так предусмотрено, то не организована ли работа вутри Delphi со статическими массивами так же как с динамическими?
← →
DrPass © (2005-10-19 21:48) [7]
> При объявлении статического массива - Delphi не выделяет
> память под его ячейки до первого обращения к ним. (по показаниям
> TaskManager, например).
> Когда узнал это - очень удивился.
Скорее всего, Delphi тут вообще не причем. Статический массив, как и все остальное, объявляется в виртуальном адресном пространстве. Пока он не используется, соответствующие страницы дремлют где-нибудь в файле подкачки. Как только произошло первое обращение к массиву, Windows достала их оттуда и предоставила программе, отсюда и рост потребления памяти.
← →
GuAV © (2005-10-19 21:51) [8]Александр Слоб. (19.10.05 19:54) [6]
Нет.
Использование task manager таким образом не даст точные результаты, если интересует выделяет ли память Delphi.
Узнать, сколько памяти выделит Delphi для переменной можно, используя SizeOf.
Для статического массива будет выделена память под каждый элемент (кроме, разумеется, случаев любых приведений типов, включая явное приведение, absolute, приведение через указатели). Для динамического будет выделенно четыре байта под указатель, память под элементы будет выделенна менеджером памяти Delphi.
Страницы: 1 вся ветка
Текущий архив: 2005.11.13;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.039 c