Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];

Вниз

Динамический массив: ошибка компилятора?   Найти похожие ветки 

 
Александр Слоб.   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.042 c
2-1130324508
serko
2005-10-26 15:01
2005.11.13
Отловить запуск другой программы


14-1129816780
CrazyDog
2005-10-20 17:59
2005.11.13
64 bit поддержка в Delphi


4-1125479680
Лобзик
2005-08-31 13:14
2005.11.13
Виртуальная сетивая карта


14-1129960960
Starcom
2005-10-22 10:02
2005.11.13
Софтина для печати фотографий размером 3,5 на 4,5 мм!


1-1130146907
MBoris
2005-10-24 13:41
2005.11.13
Как в одну ячейку StringGrid засунуть две строки?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский