Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Out of Memory - непонятки


Страницы:   1 2

Franzy ©   (2008-11-17 14:14:00) 

Пишу прогу, в которой приходится работать с большими массивами данных. Прога загружает файл STL (примитивный формат СAD, фактически - список треугольников в формате: список кооржинат узлов плюс нормаль), совершает некие операции последовательно с каждым треугольником, затем записывает результат операций в другой файл.

С тестовыми (небольшими) файлами работает. С большими - в определенный момент вылетает с ошибкой Out Of Memory. Проблема в том, что, по моим расчетам, памяти должно хватать, причем с лихвой. При счете открываю Диспетчер задач, вижу по графику, что жрет 100 мегов там, где должно хватать одного мега. Т.е. имеет место memory leak, который я не могу определить.

Объектов никаких не использую, зато использую динамические массивы (а также динамические массивы динамических массивов). Возможно, я как-то не так освобождаю память?

Вот характерный пример используемых мною структур данных:

 Type

 TBaseContour = record
   length : longint; //кол-во узлов
   node : array of longint; //список узлов базового контура
 End;

 TBaseFace = record
   contour : array of TBaseContour; //список баз. контуров грани
   nContours : longint; //Кол-во контуров в грани
   facet : array of longint; //список номеров треугольников, образующих грань
   nfacets: longint; //кол-во тр-ков
 End;

 TBaseVolume = record
   face : array of TBaseFace; //грани, образующие объект
   nFaces : longint; //кол-во граней
 end;

 Var

 volume : array of TBaseVolume;
 nVolumes : longint; // number of volumes


Заранее длины дин. массивов не известны, поэтому в процессе счета их длины меняются при необходимости с помощью SetLength.

Это глобальные структуры, которые заявляются один раз (в них записываются результаты). Плюс я при анализе каждого треугольника использую дополнительные "одноразовые" массивы (тоже динамические). Чтобы освободить память после использования такого массива я пишу: [имя массива]:=nil;  

Но складывается ощущение, что память при этом не освобождается, т.е. Windows вместо повторного использования зарезервированных ранее сегментов памяти резервирует новые...

Может, я неправильно освобождаю память? Или проблема в структурах, включающих в себя динамические массивы?


Anatoly Podgoretsky   (2008-11-17 15:13:00) [21]

> sniknik  (17.11.2008 14:57:06)  [6]

Растягивание тоже делается, если блок крайний.


Franzy   (2008-11-17 15:09:00) [22]

А если длина массива уменьшается, он как, остается на месте или тоже перезаписывается целиком в новое место?


Franzy   (2008-11-17 15:04:00) [23]

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


Sapersky   (2008-11-17 15:01:00) [24]

Franzy   (17.11.08 14:43) [4]

Ну есть такой недостаток у дельфийского менеджера памяти для версий < 2006. То ли чрезмерная фрагментация блоков у него начинается, то ли ещё что-то. Видимо, он больше рассчитан на использование в стиле TList, с выделением большого кол-ва маленьких кусочков без изменения размера.

В 2006 и далее встроен FastMM, у которого, вроде, такой проблемы нет. FastMM, кстати, можно использовать и с более ранними версиями.

Другой вариант - как уже говорили, перевыделять большими блоками. Пример:
http://sapersky.narod.ru/files/Arrays.rar


Anatoly Podgoretsky   (2008-11-17 14:59:00) [25]

> Franzy  (17.11.2008 14:43:04)  [4]

Потому что, для перераспределения массива, старый блок использовать не получится, он меньше чем нужно и поэтому будет выделяться новый блок и содержимое будет копироваться в него и будет постоянный рост памяти, на каждом шаге 2N+1
При больших размерах память быстро кончится. Нужна реализация наращивания памяти не по единицы, а например сразу на 25% и самостоятельно отслеживать выход за границу. Алгоритм реализован в TList


han_malign   (2008-11-17 14:58:00) [26]

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


sniknik   (2008-11-17 14:57:00) [27]

потому, что увеличение делается не "растягиванием" используемой под массив памяти на размер ещё одного элемента, а выделением нового блока большего на этот размер и копированием в него содержимого первого блока.
память же из под первого "теряется", т.к. выделит её повторно при запрашивании следующего блока проблематично... размер этого блока будет гарантированно меньше т.к. следующий будет ещё на единицу больше...


Anatoly Podgoretsky   (2008-11-17 14:56:00) [28]

> Franzy  (17.11.2008 14:34:02)  [2]

Ничего не меняет, массив занимает всего 4 байта, а данные хранятся в куче.


Franzy   (2008-11-17 14:43:00) [29]


> Если длина массивов каждый раз увеличивается на единицу,
>  то будет большой перерасход памяти.


Почему?


MBo   (2008-11-17 14:37:00) [30]

>Заранее длины дин. массивов не известны, поэтому в процессе счета их длины меняются при необходимости с помощью SetLength.

Если длина массивов каждый раз увеличивается на единицу, то будет большой перерасход памяти. Выход - держать счетчик использованных элементов и увеличивать длину при заолнении массива на значительное число, или увеличивать вдвое. Можно и сразу задать длину с запасом.


Franzy   (2008-11-17 14:34:00) [31]

Еще один момент: "одноразовые" динамические массивы у меня заявляются как локальные переменные (внутри процедуры-обработчика). Это что-то меняет?


tesseract   (2008-11-17 14:29:00) [32]


> Но складывается ощущение, что память при этом не освобождается,


SetLength(mass,0)? Кучу может и не отпускать, см профайлером.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо