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

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

распределение памяти в динмаическом массиве записей


Страницы:   1 2

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);

тогда и по существу поговорим.


Страницы:   1 2

Наверх

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