![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
работа с динамической памятью! [D7, XP]
Dysan © (2006-02-02 18:17:00)в программе часто использую SetLength(...)
и как мне кажеться из-за такого способа в программе часто вылетает ошибка "out of memory" и т.п. в тех места которые должны работать как часы и перепроверены много раз, а может и не вылететь и отработать как надо!
отсюда вопрос. я прав? и как тогда правильно работать с динамическими массивами?
tesseract (2006-02-04 11:48:00) [1]
возникает вопрос если Result содержит массив и передает его потом из функции другому дин. массиву то что потом происходит с Result ?
Создаётся новая переменная типа result и под неё выделятся память. После передачи result переменной действуют обычные правила работы с указателями.
Фактически это тоже самое что function Mass(...; Result: array of string).
только ещё создаётся переменная result.
в твоём примере в функцию придёт уже инициализированная переменная.
Имею в виду result после вызога останется, а вот локальные указатели инициализированные в процедуре нет. Они освободяться сразу после выхода из процедуры.
Кстати вызывать Setlength на result при частом вызове функции не рекомендую - сильно тормозит. Проще создать один массив типа TbyteBuffer (sysutils) и передвать возвращаемые значения через этот буфер.
homm (2006-02-03 18:18:00) [2]
> function Mass(...):array of string;
> begin
> SetLength(Result,100);
> ...
> end;
Фактически это тоже самое что function Mass(...; Result: array of string). Так что формально присвоения нет.
Loginov Dmitry (2006-02-03 18:00:00) [3]
> Dysan © (03.02.06 17:31) [34]
Лучше так не загоняйся, а то точно глюков не оберешься :)
Dysan (2006-02-03 17:31:00) [4]да вижу тема задела.
тогда вот еще вопрос.
если функция возвращает динамический массив
например
function Mass(...):array of string;
begin
SetLength(Result,100);
...
end;
возникает вопрос если Result содержит массив и передает его потом из функции другому дин. массиву то что потом происходит с Result ?
он сам обнуляеться ? или он передает той переменной ссылку на массив?
или остаеться в памяти? Просто читал что при присвоении одного дин. массива другому количество ссылок увеличиваеться и соответственно при убивании одного второй сам не умрет!
Поясните плиз?
Desdechado (2006-02-03 16:26:00) [5]Короче, пофилософствовали на предмет бытия и первичности.
Можно и кофе с коньяком попить, развалясь в приятной неге в кресле у камина. Желающие могут закурить трубку или сигару.
evvcom (2006-02-03 14:54:00) [6]
> TList работает только с одним типом данных - Pointer.
:)
Да собственно с самими данными он и не работает. Он только выполняет функции по сохранению, извлечению данных и вызову других функций.
Loginov Dmitry (2006-02-03 14:45:00) [7]
> evvcom © (03.02.06 14:25) [28]
> Неправда. В качестве Pointer можно записать любые данные,
> размером не превышающие SizeOf(Pointer)
Какая разница, что туда можно записать. TList работает только с одним типом данных - Pointer.
> Amoeba © (03.02.06 14:29) [29]
И для кого это?
evvcom (2006-02-03 14:31:00) [8]
> Amoeba © (03.02.06 14:29) [29]
ты бы еще весь Classes.pas выложил!
Amoeba (2006-02-03 14:29:00) [9]Стоит заглянуть внутрь 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:25:00) [10]
> Неправда. TList работает только с одним типом данных - Pointer.
Неправда. В качестве Pointer можно записать любые данные, размером не превышающие SizeOf(Pointer)
Loginov Dmitry (2006-02-03 14:23:00) [11]
> Desdechado © (03.02.06 13:26) [24]
> Возможность работы с любыми типами данных.
Неправда. TList работает только с одним типом данных - Pointer. Читать [20].
С уважением.
evvcom (2006-02-03 14:23:00) [12]
> Сравним? Свободное изме...
, оба они реализованы в Delphi, на паскале, работают под одной ОС, ... :)
Все твои перечисленные доводы (ну кроме изменения размера и в какой-то степени нумерации с 0) относятся также и к статическим массивам. Их тоже в эту линейку поставить?
Главные их 2 отличия, что мешает одно заменить другим простой заменой одной строки на другую, это:
1. Кто следит за размером порций выделения памяти.
2. В общем случае: назначение, размер и состав элемента данных самого массива.
Хотя можно сказать, что из 2-го вытекает 3-е:
3. Последовательность расположения собственно самих данных.
Desdechado (2006-02-03 13:32:00) [13]Гошик Кувшинов (03.02.06 10:22) [23]
> если ты захватываешь память на новый массив по частям, лучше
> делать это большими кусками, тогда фрагментации такой не будет
А вот это больше похоже на правду. Я запамятовал этот аспект. Кстати, в TList за это отвечает Capacity, заметно влияя на производительность при больших объемах.
Desdechado (2006-02-03 13:26:00) [14]evvcom © (03.02.06 09:49) [22]
> Из твоей цитаты как раз ничего и не видно.
> TPointerList - это тип, ничего не говорящий о способе выделения памяти.
Правильно. Цитата говорила о том, что динамический массив при работе TList не используется. Если ты усмотрел в моих словах иной смысл, то читай внимательнее в следующий раз.
>> А вот динамический очень напоминает список по своим возможностям
>> и поведению.
> Какой список? TList? Бред какой-то
Сравним? Свободное изменение размера. Возможность работы с любыми типами данных. Возможность обращения к любому элементу. Нумерация элементов с 0. Элемент фактически - адрес для данных. Все методы TList имеют прямые аналоги с операциями на массивах.
Достаточно?
Гошик Кувшинов (2006-02-03 10:22:00) [15]Тут все как-то увлеклись спорами про тлист а про вопрос забыли
короче, из-за частого выделения и освобождения памяти в куче через некоторое время будет много мелких кусков, а одного большого не будет. когда будешь выделять память на нвый массив, получишь аут оф мемори.
если ты захватываешь память на новый массив по частям, лучше делать это большими кусками. лучше всего взять больше чем потом понадобится и лишнее потом освободить, тогда фрагментации такой не будет
а ещё говорят что в 2006ой дельфе новый менеджер памяти, который умеет с этим бороться. но сам не юзал, не знаю
evvcom (2006-02-03 09:49:00) [16]
> 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.
Eraser (2006-02-02 23:06:00) [17]
> Loginov Dmitry © (02.02.06 22:59) [20]
Согласен. Впринципе эти две книги похожи.
Loginov Dmitry (2006-02-02 22:59:00) [18]И вот еще отличная книжка:
Род Стиввене "Delphi готовые алгоритмы".
Eraser (2006-02-02 22:48:00) [19]
> Dysan ©
очень советую книгу
Бакнелл. "Фундаментальные алгоритмы с структуры данных в Delphi"
Loginov Dmitry (2006-02-02 22:39:00) [20]Пардон, вывели из себя :)
Я просто таким вот образом хотел поинтересоваться, что еще за глюки имеют место быть в динамических массивах.
С уважением.