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

Вниз

работа с динамической памятью!   Найти похожие ветки 

 
Dysan ©   (2006-02-02 18:17) [0]

в программе часто использую SetLength(...)
и как мне кажеться из-за такого способа в программе часто вылетает ошибка "out of memory" и т.п. в тех места которые должны работать как часы и перепроверены много раз, а может и не вылететь и отработать как надо!
отсюда вопрос. я прав? и как тогда правильно работать с динамическими массивами?


 
Johnmen ©   (2006-02-02 18:22) [1]

Так и работать.
"out of memory" к данной процедуре прямого отношения не имеет.


 
Dysan ©   (2006-02-02 18:32) [2]

тогда обьясните мне почему программа при запуске выдает ошибку при выходе из процедуры на последней команде (причем любой! главное чтоб она была последней) после "жёской" работы с большим кол-вом динамических массивов. НО! если пройтись дебагом по всем строчкам кода то из этой самой процедуры она выйдет без проблем! и никакой ошибки не возникнет!


 
TUser ©   (2006-02-02 18:40) [3]


> тогда обьясните мне почему программа при запуске выдает
> ошибку при выходе из процедуры на последней команде (причем
> любой! главное чтоб она была последней) после "жёской" работы
> с большим кол-вом динамических массивов. НО! если пройтись
> дебагом по всем строчкам кода то из этой самой процедуры
> она выйдет без проблем! и никакой ошибки не возникнет!

Полагаю, что надо посмотреть на твой код.


 
Gero ©   (2006-02-02 18:43) [4]

> после "жёской" работы

Это как?


 
Dysan ©   (2006-02-02 18:49) [5]

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

а "жёской" это значит во время работы создаеться много разных массивов удаляються снова создаються т.п. - жесть одним словом :)


 
Darvin ©   (2006-02-02 18:58) [6]

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


 
Desdechado ©   (2006-02-02 19:59) [7]

Я с такой вешью сталкивался. Динамические массивы реализованы как-то кривовато. Понемножку (с маленькими объемами и не сильно терзая изменениями размеров) с ними работать можно. По-серьезному (десятки тысяч элементов) - вряд ли, ибо жрет многопамяти и валится на AV.
Я стал использовать TList, все пошло как по маслу. Рекомендую.

P.S. Подозреваю, что динамические массивы внутри реализованы через тот же TList, но вот как-то не так...


 
Loginov Dmitry ©   (2006-02-02 20:12) [8]


> Подозреваю, что динамические массивы внутри реализованы
> через тот же TList...


Наоборот только.


 
Desdechado ©   (2006-02-02 21:33) [9]

> Наоборот только
Не надо ля-ля. Цитирую Classes.pas
PPointerList = ^TPointerList;
TPointerList = array[0..MaxListSize - 1] of Pointer;
TList = class(TObject)
private
 FList: PPointerList;

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

А вот динамический очень напоминает список по своим возможностям и поведению.


 
Loginov Dmitry ©   (2006-02-02 22:01) [10]


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


Не совсем так. Раньше динамических массивов не было (до появления Delphi 4), однако их функции успешно выполняли, как вы выразились, "массивы фиксированной длины". С появлением динамических массивов потребность в конструкциях, подобной указанной вами, практически отпала.


 
Desdechado ©   (2006-02-02 22:07) [11]

> потребность в конструкциях практически отпала
И что, из этого начинает следовать, что TList основан на динамических массивах?
Странная логика... Тем более странная, что TList был с первой версии Дельфи, а не с 4-й.

P.S. имхо, потребность в массивах фиксированной длины (и TList тем паче) не отпадет, пока будут глюки с динамическими массивами


 
Sergey Masloff   (2006-02-02 22:08) [12]

Loginov Dmitry ©   (02.02.06 22:01) [10]
>С появлением динамических массивов потребность в конструкциях, >подобной указанной вами, практически отпала.
Извините, это бред


 
Sergey Masloff   (2006-02-02 22:13) [13]

Desdechado ©   (02.02.06 22:07) [11]
> имхо, потребность в массивах фиксированной длины (и TList тем паче) не >отпадет, пока будут глюки с динамическими массивами
И потом не отпадет потому что на фиг заморочки с управляемыми переменными когда можно просто руками быстро выделить блок памяти и максимально быстро по нему позиционироваться просто переставляя указатель а потом замочить когда не надо не возлагая это на других.
 Все же динамические массивы это несколько другое и для других целей


 
Desdechado ©   (2006-02-02 22:17) [14]

> на фиг заморочки с управляемыми переменными
именно поэтому я вставил "(и TList тем паче)"


 
Sergey Masloff   (2006-02-02 22:20) [15]

А то так можно заключить что с появлением типа Variant надобность во всех остальных типах отпала (ну или практически отпала)
;-)))


 
Loginov Dmitry ©   (2006-02-02 22:24) [16]


> Sergey Masloff   (02.02.06 22:08) [12]
>
> Loginov Dmitry ©   (02.02.06 22:01) [10]
> >С появлением динамических массивов потребность в конструкциях,
>  >подобной указанной вами, практически отпала.
> Извините, это бред


Это не есть бред. Я же не сказал, что полностью отпала. Просто сейчас благодаря динамическим массивам стало гораздо проще организовывать списки. А гражданин Desdechado ©   (02.02.06 19:59) [7] утверждает, что динамические массивы основаны на списках, что уж точно бред.


Desdechado ©   (02.02.06 22:07) [11]
> потребность в массивах фиксированной длины (и TList тем
> паче) не отпадет, пока будут глюки с динамическими массивами


Ищи глюк в себе.


 
Desdechado ©   (2006-02-02 22:29) [17]

> гражданин Desdechado ©   (02.02.06 19:59) [7] утверждает, что
> динамические массивы основаны на списках, что уж точно бред
Если ты внимательно читал пост [7], то там написано "подозреваю", а не "утверждаю". Твои же посты как раз очень категоричны и, как принято, совершенно без аргументов.

> Ищи глюк в себе
На личности переходят, когда по существу сказать нечего.


 
Loginov Dmitry ©   (2006-02-02 22:39) [18]

Пардон, вывели из себя :)
Я просто таким вот образом хотел поинтересоваться, что еще за глюки имеют место быть в динамических массивах.

С уважением.


 
Eraser ©   (2006-02-02 22:48) [19]


> Dysan ©

очень советую книгу
Бакнелл. "Фундаментальные алгоритмы с структуры данных в Delphi"


 
Loginov Dmitry ©   (2006-02-02 22:59) [20]

И вот еще отличная книжка:
Род Стиввене "Delphi готовые алгоритмы".


 
Eraser ©   (2006-02-02 23:06) [21]


> Loginov Dmitry ©   (02.02.06 22:59) [20]

Согласен. Впринципе эти две книги похожи.


 
evvcom ©   (2006-02-03 09:49) [22]


> Desdechado ©   (02.02.06 21:33) [9]
> > Наоборот только
> Не надо ля-ля. Цитирую Classes.pas
> PPointerList = ^TPointerList;
> TPointerList = array[0..MaxListSize - 1] of Pointer;
> TList = class(TObject)
> private
>  FList: PPointerList;
> Как видно, используется массив фиксированной длины, а не
> динамический.

Из твоей цитаты как раз ничего и не видно. TPointerList - это тип, ничего не говорящий о способе выделения памяти. Это просто "инструмент" для доступа к элементам списка, не более того. Надо смотреть, как выделяется память для FList: PPointerList, а в коде это делается через GetMem/ReallocMem, т.е. используя BorlandMM. Память под динамические массивы выделяется тоже через BorlandMM, но за порции (размеры) отвечает уже сам программист, и если он не понимает, из-за чего может получиться перерасход памяти, то и получает такие ошибки на дин.массивах, а на TList у него все гладко выходит. Ведь разработчики-то TList эту проблему прекрасно понимают :) Отсюда вывод, что криво устроены мозги называющего себя программистом, а не реализация динамических массивов.


> А вот динамический очень напоминает список по своим возможностям
> и поведению.

Какой список? TList? Бред какой-то. Общего у них только динамическое выделение памяти под данные через BorlandMM.


 
Гошик Кувшинов   (2006-02-03 10:22) [23]

Тут все как-то увлеклись спорами про тлист а про вопрос забыли

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

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

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


 
Desdechado ©   (2006-02-03 13:26) [24]

evvcom ©   (03.02.06 09:49) [22]
> Из твоей цитаты как раз ничего и не видно.
> TPointerList - это тип, ничего не говорящий о способе выделения памяти.
Правильно. Цитата говорила о том, что динамический массив при работе TList  не используется. Если ты усмотрел в моих словах иной смысл, то читай внимательнее в следующий раз.

>> А вот динамический очень напоминает список по своим возможностям
>> и поведению.
> Какой список? TList? Бред какой-то
Сравним? Свободное изменение размера. Возможность работы с любыми типами данных. Возможность обращения к любому элементу. Нумерация элементов с 0. Элемент фактически - адрес для данных. Все методы TList имеют прямые аналоги с операциями на массивах.
Достаточно?


 
Desdechado ©   (2006-02-03 13:32) [25]

Гошик Кувшинов   (03.02.06 10:22) [23]
> если ты захватываешь память на новый массив по частям, лучше
> делать это большими кусками, тогда фрагментации такой не будет
А вот это больше похоже на правду. Я запамятовал этот аспект. Кстати, в TList за это отвечает Capacity, заметно влияя на производительность при больших объемах.


 
evvcom ©   (2006-02-03 14:23) [26]


> Сравним? Свободное изме...

, оба они реализованы в Delphi, на паскале, работают под одной ОС, ... :)
Все твои перечисленные доводы (ну кроме изменения размера и в какой-то степени нумерации с 0) относятся также и к статическим массивам. Их тоже в эту линейку поставить?
Главные их 2 отличия, что мешает одно заменить другим простой заменой одной строки на другую, это:
1. Кто следит за размером порций выделения памяти.
2. В общем случае: назначение, размер и состав элемента данных самого массива.
Хотя можно сказать, что из 2-го вытекает 3-е:
3. Последовательность расположения собственно самих данных.


 
Loginov Dmitry ©   (2006-02-03 14:23) [27]


> Desdechado ©   (03.02.06 13:26) [24]
> Возможность работы с любыми типами данных.


Неправда. TList работает только с одним типом данных - Pointer. Читать [20].

С уважением.


 
evvcom ©   (2006-02-03 14:25) [28]


> Неправда. TList работает только с одним типом данных - Pointer.

Неправда. В качестве Pointer можно записать любые данные, размером не превышающие SizeOf(Pointer)


 
Amoeba ©   (2006-02-03 14:29) [29]

Стоит заглянуть внутрь TList:

function TList.Add(Item: Pointer): Integer;
begin
 Result := FCount;
 if Result = FCapacity then Grow;
 FList^[Result] := Item;
 Inc(FCount);
end;

function TList.Expand: TList;
begin
 if FCount = FCapacity then Grow;
 Result := Self;
end;

procedure TList.Grow;
var
 Delta: Integer;
begin
 if FCapacity > 64 then Delta := FCapacity div 4 else
   if FCapacity > 8 then Delta := 16 else
     Delta := 4;
 SetCapacity(FCapacity + Delta);
end;

procedure TList.SetCapacity(NewCapacity: Integer);
begin
 if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
   Error(SListCapacityError, NewCapacity);
 if NewCapacity <> FCapacity then
 begin
   ReallocMem(FList, NewCapacity * SizeOf(Pointer));
   FCapacity := NewCapacity;
 end;
end;

procedure TList.SetCount(NewCount: Integer);
begin
 if (NewCount < 0) or (NewCount > MaxListSize) then
   Error(SListCountError, NewCount);
 if NewCount > FCapacity then SetCapacity(NewCount);
 if NewCount > FCount then
   FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0);
 FCount := NewCount;
end;


 
evvcom ©   (2006-02-03 14:31) [30]


> Amoeba ©   (03.02.06 14:29) [29]

ты бы еще весь Classes.pas выложил!


 
Loginov Dmitry ©   (2006-02-03 14:45) [31]


> evvcom ©   (03.02.06 14:25) [28]
> Неправда. В качестве Pointer можно записать любые данные,
>  размером не превышающие SizeOf(Pointer)


Какая разница, что туда можно записать. TList работает только с одним типом данных - Pointer.


> Amoeba ©   (03.02.06 14:29) [29]


И для кого это?


 
evvcom ©   (2006-02-03 14:54) [32]


> TList работает только с одним типом данных - Pointer.

:)
Да собственно с самими данными он и не работает. Он только выполняет функции по сохранению, извлечению данных и вызову других функций.


 
Desdechado ©   (2006-02-03 16:26) [33]

Короче, пофилософствовали на предмет бытия и первичности.
Можно и кофе с коньяком попить, развалясь в приятной неге в кресле у камина. Желающие могут закурить трубку или сигару.


 
Dysan ©   (2006-02-03 17:31) [34]

да вижу тема задела.
тогда вот еще вопрос.
если функция возвращает динамический массив
например
function Mass(...):array of string;
begin
SetLength(Result,100);
...
end;
возникает вопрос если Result содержит массив и передает его потом из функции другому дин. массиву то что потом происходит с Result ?
он сам обнуляеться ? или он передает той переменной ссылку на массив?
или остаеться в памяти? Просто читал что при присвоении одного дин. массива другому количество ссылок увеличиваеться и соответственно при убивании одного второй сам не умрет!
Поясните плиз?


 
Loginov Dmitry ©   (2006-02-03 18:00) [35]


> Dysan ©   (03.02.06 17:31) [34]


Лучше так не загоняйся, а то точно глюков не оберешься :)


 
homm ©   (2006-02-03 18:18) [36]


> function Mass(...):array of string;
> begin
> SetLength(Result,100);
> ...
> end;

Фактически это тоже самое что function Mass(...; Result: array of string). Так что формально присвоения нет.


 
tesseract ©   (2006-02-04 11:48) [37]


возникает вопрос если Result содержит массив и передает его потом из функции другому дин. массиву то что потом происходит с Result ?


Создаётся новая переменная типа result и под неё выделятся память. После передачи result переменной действуют обычные правила работы с указателями.

Фактически это тоже самое что function Mass(...; Result: array of string).

только ещё создаётся переменная result.
в твоём примере в функцию придёт уже инициализированная переменная.

Имею в виду result после вызога останется, а вот локальные  указатели инициализированные  в процедуре нет. Они освободяться сразу после выхода из  процедуры.

Кстати вызывать Setlength на  result при частом вызове функции не рекомендую - сильно тормозит. Проще создать один массив типа TbyteBuffer (sysutils) и передвать возвращаемые значения через этот буфер.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2006.02.19;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.56 MB
Время: 0.048 c
10-1113923505
Kerk
2005-04-19 19:11
2006.02.19
How Child IDs Are Used in Parameters


4-1133808278
solomon
2005-12-05 21:44
2006.02.19
Internet Explorer, фрейм и отлов нажатия кнопок в нем.


11-1119593161
Trubis
2005-06-24 10:06
2006.02.19
Demo KOLListView


2-1138126468
aviseral
2006-01-24 21:14
2006.02.19
Работа с MS Excel


6-1131478836
Bruce
2005-11-08 22:40
2006.02.19
Задержка при отправке данных. Indy.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский