![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
распределение памяти в динмаическом массиве записей
Nil © (2007-12-06 14:47:00)С виду тревиальная задача: нужен динамический массив элементами которго являются записи. Вот что я налабал:
const
MAXDRVCOUNT=1000;
type
pDrvRec = ^TDrvRec;
TDrvRec=record
ClassName,
ClassGUID,
DevName,
HardwareID,
CompatibleIDS,
DeviceClassName,
Manufacturer,
FriendlyName,
DriverDate,
ProviderName,
DriverVersion,
DriverDesc: string[255];
ClassIm: integer;
end;
PDrvArr = ^TDrvArr;
TDrvArr = array [1..MAXDRVCOUNT] of pDrvRec;
public
{ Public declarations }
DrvList: pDrvArr;
.................
for I := 1 to 100 do
begin
ReAllocMem(MainForm.DrvList,i*sizeof(TDrvRec)+4);
MainForm.DrvList[i]^.ClassName:= 'Hello'; - вот здесь AcessViolation
end;
не понятно почему ошибка возникает на 3-м шаге цикла. подскажите пож где грабли?
заранее благодарен
Nil (2007-12-07 20:11:00) [1]
> Имхо, сей "надыбанный" пример был для ТурбоПаскаль или для
> младших версий Дельфи, когда ещё не было динамических массивов.
> Тогда это было единственным способом реализовать массив
> с заранее (на этапе компиляции) не известными размерами.
>
вот теперь легче спать) я просто помню со времён паскаля я как то очень сильно извращался чтобы такое сделать, поэтому и зацепился за этот пример
> Alex
так и сделал
всем спасибо за разъяснения!
Palladin (2007-12-07 15:26:00) [2]
> Галинка © (07.12.07 15:24) [26]
рецепт был выписан давно, еще в самом начале, больной не поддался лечению
Галинка (2007-12-07 15:24:00) [3]Palladin © (07.12.07 15:10) [23]
ну понятно. Там же массив фиксированных размеров. Поддерживаю рецепт Алекса.
Palladin (2007-12-07 15:17:00) [4]
> Alex (07.12.07 15:12) [24]
проще, но у автора бзик сделать через содранный пример
Alex (2007-12-07 15:12:00) [5]А не проще сделать так:
type
TMyRecord = ... end;
var
MyVar:array of TMyRecord;
begin
SetLength(MyVar, скока хочешь)
for i:=0 to Length(MyVar)-1 do
begin
делаешь с MyVar[i] че хочешь
end;
:))))))))))
end;
Palladin (2007-12-07 15:10:00) [6]
> Галинка © (07.12.07 15:01) [22]
это в случае динамических массивов, в случае
PMyArr=^TMyArr
TMyArr=Array [0..1] of чего то там
такое не сканает
Галинка (2007-12-07 15:01:00) [7]Вот и я о том же. Или не динамический, читай не массив переменной длины. Или зачем тогда максимальную длину сразу выделять?
Palladin © (07.12.07 13:43) [21]
конечно не зная задачи трудно сказать. Но чтобы обратится к пятому элементу, надо всего лишь сделать SetLength(<arr_name>, 5). И он уже будет. Так что по идее AV уже не должно вываливаться?
Palladin (2007-12-07 13:43:00) [8]
> Галинка © (07.12.07 11:40) [19]
очень даже пригодится на этапе компиляции в случае обращения к фиксированным индексам массива
Anatoly Podgoretsky (2007-12-07 12:10:00) [9]Пригодится, только называеть его динамическим не стоит.
Галинка (2007-12-07 11:40:00) [10]осмелюсь предположить, что [1..MAXDRVCOUNT] не пригодится в принципе.
Германн (2007-12-07 01:22:00) [11]
> Nil (07.12.07 01:01) [17]
>
...
> > Германн
> т.е. если всё таки уперется рогами в мой случай то получается
> нужно сначала
> ReAllocMem(MainForm.DrvList,1*sizeof(pDrvRec)); это инициализация
> нового элемента в массиве
> а потом
> ReAllocMem(MainForm.DrvList[1],1*sizeof(TDrvRec)); это инициализация
> содержимого этого элемента
> правильно понял?
>
Не. Лучше описать массив TDrvArr какarray [1..MAXDRVCOUNT] of TDrvRec;
Тогда всё остальное будет верным. Ну и ещё плюс четверку выбросить надо :)
А описывать вышеуказанный массив какarray [1..MAXDRVCOUNT] of pDrvRec;просто глупо.
Имхо, сей "надыбанный" пример был для ТурбоПаскаль или для младших версий Дельфи, когда ещё не было динамических массивов. Тогда это было единственным способом реализовать массив с заранее (на этапе компиляции) не известными размерами.
Nil (2007-12-07 01:01:00) [12]> Юрий Зотов
вери мач как говорится!) завтра попробую
> Германн
т.е. если всё таки уперется рогами в мой случай то получается нужно сначала
ReAllocMem(MainForm.DrvList,1*sizeof(pDrvRec)); это инициализация нового элемента в массиве
а потом
ReAllocMem(MainForm.DrvList[1],1*sizeof(TDrvRec)); это инициализация содержимого этого элемента
правильно понял?
> Rouse_
спасибо этот пример уже видел, у меня немножко другая задача, автообновление драйверов на компе, хотя с этого примера много полезного почерпнул. больше понравились демки из jediapilib
кста, http://rouse.drkb.ru/много интересной инфы. отдельное спасибо!
Rouse_ (2007-12-06 21:28:00) [13]Мошт это подойдет?
http://rouse.drkb.ru/tmp/devlist.zip
> увидел скелет в каком то примере ну и развил его до своей
> задачи
Это действительно скелет, и чтоб вдохнуть в него жизнь нужно память под все элементы выделить. Указатель на массив указателей - а что? Креатиф :)))
Германн (2007-12-06 21:18:00) [14]
> > Германн ©
>
> sizeof(TDrvRec) я так понимаю 12*255+4=3064 байт
> изначально под MainForm.DrvList выделено 0 байт
>
> ReAllocMem(MainForm.DrvList,1*sizeof(TDrvRec));
> теперь MainForm.DrvList 3064
>
> ReAllocMem(MainForm.DrvList,2*sizeof(TDrvRec));
> теперь MainForm.DrvList 3064*2 и это уже 2 элемента в массиве
> и т.д.
>
> я правильно понимаю как это работает? если нет поправьте
> пож, хочется всё таки понять как с такими зверями обращаться
> в будущем
>
Нет неправильно. Потому что массив DrvList: pDrvArr; это массив указателей на структуры, а не массив самих структур. А вот под сами структуры ты как раз память не выделял. Оттуда и AV.
Юрий Зотов (2007-12-06 19:58:00) [15]> Nil (06.12.07 19:50) [13]
> а при таком подходе SetLength использовать для добавления?
Да. Точнее, для изменения длины при добавлении (или сокращении).
> ничего что там нестандартный тип данных, а мною придуманный?
Нормально, никакой разницы нет.
> чтобы инициализировать ещё один элемент в массиве нужен
SetLength(MainForm.DrvList, Length(MainForm.DrvList) + 1);
Этот код добавляет в конец массива еще один элемент. И никаких GetMem. Элемент уже готов и с ним можно работать.
Nil (2007-12-06 19:50:00) [16]> Palladin
> почему делаем реаллок по размеру SizeOf(TDrvRec) да еще +4
+4 это уже пальцем в небо тыкал, не обращайте внимания, а SizeOf(TDrvRec) я так понимаю чтобы добавить новый элемент к массиву, нужно выделить столько сколько занимает моя запись. или ошибаюсь?
> Юрий Зотов
а при таком подходе SetLength использовать для добавления? ничего что там нестандартный тип данных, а мною придуманный? я раньше с такими массивами не сталкивался, когда то в теории было, не помню, так что прошу не бранится за возможно глупые высказывания по этому поводу
я так понимаю чтобы инициализировать ещё один элемент в массиве нужен
SetLength(MainForm.DrvList,1);
GetMem(MainForm.DrvList, sizeof(TDrvRec));
правильно понял? или GetMem в этом случае уже не нужен?
> Германн ©
sizeof(TDrvRec) я так понимаю 12*255+4=3064 байт
изначально под MainForm.DrvList выделено 0 байт
ReAllocMem(MainForm.DrvList,1*sizeof(TDrvRec));
теперь MainForm.DrvList 3064
ReAllocMem(MainForm.DrvList,2*sizeof(TDrvRec));
теперь MainForm.DrvList 3064*2 и это уже 2 элемента в массиве и т.д.
я правильно понимаю как это работает? если нет поправьте пож, хочется всё таки понять как с такими зверями обращаться в будущем
Юрий Зотов (2007-12-06 19:25:00) [17]> Nil (06.12.07 14:47)
Динамический масив МОЖНО реализовать через указатели, но, взявшись за это, надо, как минимум, понимать, что такое указатели и как с ними работать (сколько и когда выделять памяти, как с нею обращаться, когда ее освобождать и т.п.). И если с этим есть проблемы, то гораздо проще использовать дельфишные динамические массивы:
type
TDrvRec = record
...
end;
var
DrvArr: array of TDrvRec;
Это все, что требуется. И никаких указателей. И имеем самый настоящий динамический массив. Как с ними работать - см. в справке топик "Dynamic Arrays".
Сергей М. (2007-12-06 15:52:00) [18]
> Nil (06.12.07 15:43) [7]
По существу - если нужен динамический массив, следует объявить именно динамический массив. В чем проблема ?
Германн (2007-12-06 15:46:00) [19]Тимур опередил :)
Германн (2007-12-06 15:46:00) [20]
> а по существу вопроса можете что нибудь предложить, кроме
> того что вы увидели [1..MAXDRVCOUNT]
Объясни сперва эту вот строчку
> ReAllocMem(MainForm.DrvList,i*sizeof(TDrvRec)+4);
тогда и по существу поговорим.