![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамические массивы vs Статические массивы [D7, WinXP]
SH@RK © (2007-01-31 12:47:00)Существуют алгоритмы, память для работы которых выделяется во время их работы. Т.е. заранее неизвестен размер массива, с которым работает алгоритм.
Пример:
type
TNode = packed record
Child: packed array [0..31] of Word;
Parent: Word;
Final: LongBool;
end;
PArrNode = packed array of TNode;
var
Node: PArrNode; // динамич. массив
1)
В ходе выполнения алгоритма выделяю память кусками (по мере неоходимости):
Len := Length(Node);
SetLength(Node, Len + 100);
Я полагаю, что при этом элементы массива Node2^ располагаются в виртуальной памяти последовательно. Поэтому я допускаю работу с этим массивом как со статическим:
....
type
PArrNodeSt = ^TArrNodeSt;
TArrNodeSt = packed array [0..0] of TNode;
....
PArrNodeSt(Node)^[i] := ....
Вообще это дупустимо?
2)
Когда во внешней программе просчитывается этот алгоритм, то в файл с данными я записываю и кол-во элементов массива.
Поэтому в основной программе я выделяю память под этот массив при помощи GetMem (юзаю FastMM4).
Но при чтении этого массива как динамического (x := Node[i]), иногда возникают ошибки. Ошибки происходят в ф-ии модуля System @DynArrayClear (@FreeMem).
Как это понимать? При обычном чтении динамического массива происходит обращение к ф-иям выделения/освобождения памяти?
Теперь при любом методе выделения памяти под массив работаю с ним как со статическим массивом. Это допустимо?
Desdechado (2007-02-01 11:18:00) [21]Amoeba © (31.01.07 16:07) [18]
Еще один. Читай Desdechado © (31.01.07 15:41) [12]
jack128 (2007-02-01 00:35:00) [22]Сергей М. © (31.01.07 16:11) [19]
Просто компилятор не позволит сделать приведение типа а-ля
PMyType(MyDynArray)[someindex]
Почему не позволит?? Дин массив - суть указатель. Так тчо его можно привести к любому "указательному" типу.
type
TDynIntegerArray = array of Integer;
TStaticIntegerArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer;
PStaticIntegerArray = ^TStaticIntegerArray;
procedure TForm9.FormCreate(Sender: TObject);
var
Arr: TDynIntegerArray;
begin
SetLength(Arr, 1);
PStaticIntegerArray(Arr)[0] := 10;
Caption := IntToStr(Arr[0])
end;
Или я что то не так понял?
SH@RK © (31.01.07 16:24) [21]
Всё. Нафиг эти дин. массивы. Сделаю два варианта модуля:
1) с отдельным выделением памяти под элемент (New);
2) с глобальным выделением памяти под все элементы (GetMem);
Почему нафиг?? С New/GetMem - гораздо больше ошибок огребешь, чем с дин массивами
OSA (2007-01-31 16:41:00) [23]
> Дык, она всегда будет выделяться последовательно. Потому
> и многократный вызов SetLength — крайне опасная штука.
> По поводу остального — никак не могу понять, чем динамические
> массивы не угодили? :)
> Если же задача такова, что приходится часто добавлять-удалять
> элементы, то лучший выбор — списки. Во многих случаях хватит
> стандартного класса TList.
Поробую объяснить научно-популярно.
Первый способ как раз и использует TList. Но в этом способе памяти требуется в 2 раза больше, т.к. каждая ссылка на элемент дерева Ахо-Корасик представляет собой Pointer.
Второй способ использует относительные ссылки на элементы в виде Word.
ЗЫ. Уже всё сделал и протестировал.
Джо (2007-01-31 16:28:00) [24]> [21] SH@RK © (31.01.07 16:24)
> При использовании в D7+FastMM4 динамического массива память
> для него выделяется последовательно.
Дык, она всегда будет выделяться последовательно. Потому и многократный вызов SetLength — крайне опасная штука.
По поводу остального — никак не могу понять, чем динамические массивы не угодили? :)
Если же задача такова, что приходится часто добавлять-удалять элементы, то лучший выбор — списки. Во многих случаях хватит стандартного класса TList.
SH@RK (2007-01-31 16:24:00) [25]При использовании в D7+FastMM4 динамического массива память для него выделяется последовательно. Во всяком случае у меня 6 мегабайтный массив именно так расположился =)
Всё. Нафиг эти дин. массивы. Сделаю два варианта модуля:
1) с отдельным выделением памяти под элемент (New);
2) с глобальным выделением памяти под все элементы (GetMem);
Всё равно данные подготавливаются в отдельном приложении (там буду юзать 1 модуль), в котором узнаю число элементов.
А в главной прожке буду работать со 2 модулем, благо в данных уже содержится кол-во элементов (что бы память экономилась).
Джо (2007-01-31 16:21:00) [26]Автору по поводу SetLength. По возможности, следует избегать, как чумы, частого вызова SetLength. Что для длинных строк, что для дин. массивов. То есть, эти вызовы нужно сводить к наименьшему возможному количеству, в идеале — к одному. Дабы избежать дорогостоящего перераспределения памяти, к которому эти вызовы могут приводить.
Сергей М. (2007-01-31 16:11:00) [27]
> jack128 © (31.01.07 15:59) [16]
Ну если это принципиально, то да.
Просто компилятор не позволит сделать приведение типа а-ля
PMyType(MyDynArray)[someindex]
Amoeba (2007-01-31 16:07:00) [28]
> Desdechado © (31.01.07 15:18) [10]
>
> Врать не буду, но имхо не стоит особенно расчитывать на
> то, что новые элементы динамического массива располагаются
> последовательно и строго за старыми. Внутренняя реализация
> скорее напоминает список, в который помять может выделяться
> произвольными кусками в произвольных местах, что очень сильно
> зависит от фрагментации памяти и от работы менеджера памяти.
> А менеджеры у разных версий разные, а можно и вообще свои
> подключать.
>
Определенно врешь!
Anatoly Podgoretsky (2007-01-31 16:00:00) [29]> SH@RK (31.01.2007 12:47:00) [0]
Справка: Do not apply the dereference operator (^) to a dynamic-array variable
jack128 (2007-01-31 15:59:00) [30]Сергей М. © (31.01.07 13:05) [2]
Переменная типа дин.массив есть суть указатель на управляющую структуру этого массива, а не на собственно данные, хранимые массивом.
не-а. "управляющая структура" находится по отрицательному смещению от указателя. Так же как и длинных строках. Собственно длинные строки - частный случай дин массивов.
Сергей М. (2007-01-31 15:52:00) [31]
> не знаю я как заранее просчитать кол-во элементов автомата
> Ахо-Корасик.
>
А причем здесь это ?
Речь-то идет о перераспределении памяти на момент когда требуется добавить элемент(ы) ... А к карасик там или не карасик потребовал от тебя это - совершенно не важно ...
SH@RK (2007-01-31 15:44:00) [32]Первоначальный вариант алгоритма работал вот с такой структурой:
type
PNode = ^TNode;
TNode = record
Child: array [0..255] of PNode;
Parent: PNode;
Final: LongBool;
end;
В каждом элементе имеются ссылки на другие элементы.
Память под каждый элемент выделялась при помощи New.
Но эта реализация много памяти жрёт.
Вот и приходится думать как всё это дело оптимизировать.
ЗЫ. Ну не знаю я как заранее просчитать кол-во элементов автомата Ахо-Корасик.
evvcom (2007-01-31 15:42:00) [33]> [7] Сергей М. © (31.01.07 13:28)
> Динамические придуманы для лентяев и батонокидателей)
Значит я лентяй или батонокидатель или и то, и другое :)
Хотя нет. Я могу и со статическими типа управиться. Значит только лентяй :)
> [10] Desdechado © (31.01.07 15:18)
> но имхо не стоит особенно расчитывать
Фиг знает. Это надо доки смотреть. Но думаю, можно.
> что новые элементы динамического массива располагаются последовательно
> и строго за старыми
До D7 включительно именно так и располагаются.
> Внутренняя реализация скорее напоминает список, в который
> помять может выделяться произвольными кусками в произвольных
> местах
По D7 не так.
Desdechado (2007-01-31 15:41:00) [34]> Но тем не менее врешь)
Возможно. Но хотелось бы узнать, в чем именно. Желательно со ссылкой на документацию.
ЗЫ Я в этих тонкостях детально не разбирался, т.к. считаю, что нечего смешивать механизмы прямого доступа по адресу с нормальными языковыми конструкциями.
Сергей М. (2007-01-31 15:25:00) [35]
> Desdechado © (31.01.07 15:18) [10]
> Врать не буду
Но тем не менее врешь)
Desdechado (2007-01-31 15:18:00) [36]Врать не буду, но имхо не стоит особенно расчитывать на то, что новые элементы динамического массива располагаются последовательно и строго за старыми. Внутренняя реализация скорее напоминает список, в который помять может выделяться произвольными кусками в произвольных местах, что очень сильно зависит от фрагментации памяти и от работы менеджера памяти. А менеджеры у разных версий разные, а можно и вообще свои подключать.
Сергей М. (2007-01-31 14:10:00) [37]
> SH@RK © (31.01.07 13:50) [8]
Угу. Либо загажена.
Чем списки-от не угодили ?
SH@RK (2007-01-31 13:50:00) [38]Т.е. , как я понял, ошибка @DynArrayClear возникала из-за того что не была сформирована управляющая структурамассива !?
Сергей М. (2007-01-31 13:28:00) [39]
> чем отличаются динамические от статических массивов
Динамические придуманы для лентяев и батонокидателей)
SH@RK (2007-01-31 13:26:00) [40]точно подмечено =)
сорри