Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.01.06;
Скачать: CL | DM;

Вниз

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

 
Nil   (2007-12-06 14:47) [0]

С виду тревиальная задача: нужен динамический массив элементами которго являются записи. Вот что я налабал:

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-м шаге цикла. подскажите пож где грабли?

заранее благодарен


 
Dib@zol ©   (2007-12-06 14:50) [1]

А не легше ли так:
DrvList:array of TDrvRec + SetLength + Finalize
???


 
Юрий Зотов ©   (2007-12-06 15:00) [2]

> Nil   (06.12.07 14:47)

Да... понакручено. Указатель на массив указателей....

Зачем усложнять жизнь самому себе? Если нужен динамический масив, так динамический массив и используйте, без всякого мудрежа.


 
Nil   (2007-12-06 15:19) [3]

> Dib@zol
увидел скелет в каком то примере ну и развил его до своей задачи
а под Finalize что подразумевается?


 
Германн ©   (2007-12-06 15:20) [4]

Ну разве что для ТП.


 
Сергей М. ©   (2007-12-06 15:32) [5]


> нужен динамический массив


> Вот что я налабал


В "налабанном" динамическим массивом и не пахнет.


 
Германн ©   (2007-12-06 15:41) [6]


> В "налабанном" динамическим массивом и не пахнет.

В "налабанном" пахнет граблями, что автор и сам признал. А не надо бездумно тащить из тырнета всё то барахло, которое там валяется с незапамятных времен.


 
Nil   (2007-12-06 15:43) [7]

> Сергей М.
спасибо что заметили!!
обратите внимание на тему "нужен динамический массив" а не "есть динамический массив"
а по существу вопроса можете что нибудь предложить, кроме того что вы увидели [1..MAXDRVCOUNT]?


 
Palladin ©   (2007-12-06 15:45) [8]

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; // размер элемента массива = SizeOf(pDrvRec)

public
  { Public declarations }

  DrvList: pDrvArr;

.................

for I := 1 to 100 do
begin
  ReAllocMem(MainForm.DrvList,i*sizeof(TDrvRec)+4); // почему делаем реаллок по размеру SizeOf(TDrvRec) да еще +4

  MainForm.DrvList[i]^.ClassName:= "Hello"; - вот здесь AcessViolation // почему обращаемся к неинициализированному указателю?
end;


 
Германн ©   (2007-12-06 15:46) [9]


> а по существу вопроса можете что нибудь предложить, кроме
> того что вы увидели [1..MAXDRVCOUNT]

Объясни сперва эту вот строчку
> ReAllocMem(MainForm.DrvList,i*sizeof(TDrvRec)+4);

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


 
Германн ©   (2007-12-06 15:46) [10]

Тимур опередил :)


 
Сергей М. ©   (2007-12-06 15:52) [11]


> Nil   (06.12.07 15:43) [7]


По существу - если нужен динамический массив, следует объявить именно динамический массив. В чем проблема ?


 
Юрий Зотов ©   (2007-12-06 19:25) [12]

> Nil   (06.12.07 14:47)  

Динамический масив МОЖНО реализовать через указатели, но, взявшись за это, надо, как минимум, понимать, что такое указатели и как с ними работать (сколько и когда выделять памяти, как с нею обращаться, когда ее освобождать и т.п.). И если с этим есть проблемы, то гораздо проще использовать дельфишные динамические массивы:

type
 TDrvRec = record
   ...
 end;

var
 DrvArr: array of TDrvRec;

Это все, что требуется. И никаких указателей. И имеем самый настоящий динамический массив. Как с ними работать - см. в справке топик "Dynamic Arrays".


 
Nil   (2007-12-06 19:50) [13]

> 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:58) [14]

> Nil   (06.12.07 19:50) [13]

> а при таком подходе SetLength использовать для добавления?
Да. Точнее, для изменения длины при добавлении (или сокращении).

> ничего что там нестандартный тип данных, а мною придуманный?
Нормально, никакой разницы нет.

> чтобы инициализировать ещё один элемент в массиве нужен
SetLength(MainForm.DrvList, Length(MainForm.DrvList) + 1);
Этот код добавляет в конец массива еще один элемент. И никаких GetMem. Элемент уже готов и с ним можно работать.


 
Германн ©   (2007-12-06 21:18) [15]


> > Германн ©
>
> 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.


 
Rouse_ ©   (2007-12-06 21:28) [16]

Мошт это подойдет?
http://rouse.drkb.ru/tmp/devlist.zip

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

Это действительно скелет, и чтоб вдохнуть в него жизнь нужно память под все элементы выделить. Указатель на массив указателей - а что? Креатиф :)))


 
Nil   (2007-12-07 01:01) [17]

> Юрий Зотов
вери мач как говорится!) завтра попробую

> Германн
т.е. если всё таки уперется рогами в мой случай то получается нужно сначала
ReAllocMem(MainForm.DrvList,1*sizeof(pDrvRec)); это инициализация нового элемента в массиве
а потом
ReAllocMem(MainForm.DrvList[1],1*sizeof(TDrvRec)); это инициализация содержимого этого элемента
правильно понял?

> Rouse_
спасибо этот пример уже видел, у меня немножко другая задача, автообновление драйверов на компе, хотя с этого примера много полезного почерпнул. больше понравились демки из jediapilib
кста, http://rouse.drkb.ru/ много интересной инфы. отдельное спасибо!


 
Германн ©   (2007-12-07 01:22) [18]


> 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; просто глупо.
Имхо, сей "надыбанный" пример был для ТурбоПаскаль или для младших версий Дельфи, когда ещё не было динамических массивов. Тогда это было единственным способом реализовать массив с заранее (на этапе компиляции) не известными размерами.


 
Галинка ©   (2007-12-07 11:40) [19]

осмелюсь предположить, что [1..MAXDRVCOUNT] не пригодится в принципе.


 
Anatoly Podgoretsky ©   (2007-12-07 12:10) [20]

Пригодится, только называеть его динамическим не стоит.


 
Palladin ©   (2007-12-07 13:43) [21]


> Галинка ©   (07.12.07 11:40) [19]

очень даже пригодится на этапе компиляции в случае обращения к фиксированным индексам массива


 
Галинка ©   (2007-12-07 15:01) [22]

Вот и я о том же. Или не динамический, читай не массив переменной длины. Или зачем тогда максимальную длину сразу выделять?

Palladin ©   (07.12.07 13:43) [21]

конечно не зная задачи трудно сказать. Но чтобы обратится к пятому элементу, надо всего лишь сделать SetLength(<arr_name>, 5). И он уже будет. Так что по идее AV уже не должно вываливаться?


 
Palladin ©   (2007-12-07 15:10) [23]


> Галинка ©   (07.12.07 15:01) [22]

это в случае динамических массивов, в случае
PMyArr=^TMyArr
TMyArr=Array [0..1] of чего то там
такое не сканает


 
Alex   (2007-12-07 15:12) [24]

А не проще сделать так:

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:17) [25]


> Alex   (07.12.07 15:12) [24]

проще, но у автора бзик сделать через содранный пример


 
Галинка ©   (2007-12-07 15:24) [26]

Palladin ©   (07.12.07 15:10) [23]

ну понятно. Там же массив фиксированных размеров. Поддерживаю рецепт Алекса.


 
Palladin ©   (2007-12-07 15:26) [27]


> Галинка ©   (07.12.07 15:24) [26]

рецепт был выписан давно, еще в самом начале, больной не поддался лечению


 
Nil   (2007-12-07 20:11) [28]


> Имхо, сей "надыбанный" пример был для ТурбоПаскаль или для
> младших версий Дельфи, когда ещё не было динамических массивов.
>  Тогда это было единственным способом реализовать массив
> с заранее (на этапе компиляции) не известными размерами.
>


вот теперь легче спать) я просто помню со времён паскаля я как то очень сильно извращался чтобы такое сделать, поэтому и зацепился за этот пример


> Alex

так и сделал

всем спасибо за разъяснения!



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

Текущий архив: 2008.01.06;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.012 c
2-1197286618
Quart
2007-12-10 14:36
2008.01.06
Выгрузка


15-1196673637
ПЛОВ
2007-12-03 12:20
2008.01.06
Утилизация старой комп. техники


2-1197352608
Alexandr Malygin
2007-12-11 08:56
2008.01.06
арифметика


2-1197048755
Leonid
2007-12-07 20:32
2008.01.06
ComboBox и Object


2-1197197786
{ент
2007-12-09 13:56
2008.01.06
Чайник