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

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

Динамические массивы [D6, Win2k]


vint45 ©   (2005-01-25 14:29:00) 

Привет! Подскажите, будет ли правильно работать конструкция состоящая из динамического массива, элементами которого являются записи record. Причем записи содержат в себе длинные строки:

 TDescHotKey = record
  FormComp: integer;
  Param: string; // ansistring
  ShortCut: word;
  IsNew: boolean;
 end;
 THotKeys = array of TDescHotKey;

Так вот, при работе с массивом THotKeys у меня возникают ошибки, после нескольких операций присваивания и перераспределения его элементов.


vint45   (2005-01-26 10:15:00) [1]


> Separator ©   (25.01.05 17:13) [16]
> И не забывай очищать после себя память

это напутствие или я действительно неправильно освобождаю память? :)
Спасибо, за PChar, но вопрос про строки остался открытым: почему неверно освобождается память под них, может это как-то связано со счетчиком обращений к ним? Вначале ветки меня уверяли, что со строками работать можно, так да или нет?


Sapersky   (2005-01-25 17:31:00) [2]

Нельзя двигать длиные строки!

см. TStringList.Delete (Classes.pas)


Separator   (2005-01-25 17:13:00) [3]

И не забывай очищать после себя память


Separator   (2005-01-25 17:11:00) [4]

Используй PChar и все будет ок:

type
 THKActions = (hkaChoiceElList);
 TDescHotKey = record
   FormComp: integer;
   Param: PChar;
   Action: THKActions;
   ShortCut: word;
   IsNew: boolean;
  end;
 THotKeys = array of TDescHotKey;

 TForm1 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   arrHotKeys: THotKeys;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
   SetLength(arrHotKeys,Length(arrHotKeys)+1);
   arrHotKeys[High(arrHotKeys)].FormComp:=0;
   arrHotKeys[High(arrHotKeys)].Param:= StrNew('1');
   arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
   arrHotKeys[High(arrHotKeys)].ShortCut:=118;
   SetLength(arrHotKeys,Length(arrHotKeys)+1);
   arrHotKeys[High(arrHotKeys)].FormComp:=0;
   arrHotKeys[High(arrHotKeys)].Param:= StrNew('5');
   arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
   arrHotKeys[High(arrHotKeys)].ShortCut:=119;
   SetLength(arrHotKeys,Length(arrHotKeys)+1);
   arrHotKeys[High(arrHotKeys)].FormComp:=0;
   arrHotKeys[High(arrHotKeys)].Param:= StrNew('17');
   arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
   arrHotKeys[High(arrHotKeys)].ShortCut:=121;
end;

procedure TForm1.Button1Click(Sender: TObject);
var prArrHotKeys: THotKeys;
begin
   prArrHotKeys:=Copy(arrHotKeys);
   // óäàëÿåì ïåðâûé ýëåìåíò ñ èíäåêñîì 0
   StrDispose(prArrHotKeys[0].Param);
   Move(prArrHotKeys[0+1],prArrHotKeys[0],(Length(prArrHotKeys)-1-0)*SizeOf(TDescHotKey));
   SetLength(prArrHotKeys,Length(prArrHotKeys)-1);
   // óäàëÿåì ýëåìåíò
   SetLength(prArrHotKeys,Length(prArrHotKeys)+1);
   prArrHotKeys[High(prArrHotKeys)].FormComp:=0;
   prArrHotKeys[High(prArrHotKeys)].Param:= StrNew('0');
   prArrHotKeys[High(prArrHotKeys)].Action:=hkaChoiceElList;
   prArrHotKeys[High(prArrHotKeys)].ShortCut:=116;
   Label1.Caption:=prArrHotKeys[0].Param;
   arrHotKeys:=Copy(prArrHotKeys);
   SetLength(prArrHotKeys, 0);
   Label1.Caption:=arrHotKeys[0].Param;
end;


Erik1   (2005-01-25 17:05:00) [5]

Нельзя двигать длиные строки! Перейди на тип ShortString.


vint45   (2005-01-25 16:57:00) [6]

а причем здесь сами строки, мы же в Move двигаем только указатели на них, соответственно SizeOf считает размер указателя.


Separator   (2005-01-25 16:48:00) [7]

попробуй вычислять память каждой записи как: SizeOf(TDescHotKey) + СуммаВсех .Param


vint45   (2005-01-25 16:43:00) [8]

гмм.. я тоже предполагал, что дело связано с выбождением строки, поэтому до процедуры Move явно высвобождал используемую под нее память:
Dispose(arrHotKeys[inc1].Param);
Move(...

но это не помогло.


Separator   (2005-01-25 16:39:00) [9]

Ошибка в SizeOf(TDescHotKey), так как используеться тип String, то размер будет вычесляться не правильно


vint45   (2005-01-25 16:36:00) [10]

Пробовал, при третьем нажатии кнопки, сразу на входе процедуры массив имеет неправильную структуру.


Poirot   (2005-01-25 16:33:00) [11]

Попробуй походить дебагером


vint45   (2005-01-25 16:29:00) [12]

Да, всегда. Т.е. вначале он инициализируется до трех элементов, а потом при каждом нажатии кнопки, удаляется и добавляется по одному элементу. 0+1 - это я просто так (для наглядности) оставил, 0 - это индекс массива, в данном случае удаляется первый элемент, а добавляется в конец массива.


begin...end   (2005-01-25 16:21:00) [13]

> [5] vint45   (25.01.05 16:13)

> Move(prArrHotKeys [0+1],prArrHotKeys[0],...)

Всегда ли перед нажатием кнопки массив состоит более чем из одного элемента?


vint45   (2005-01-25 16:13:00) [14]

Вот, сделал код покомпактней:

type
 THKActions = (hkaChoiceElList);
 TDescHotKey = record
  FormComp: integer;
  Param: string;
  Action: THKActions;
  ShortCut: word;
  IsNew: boolean;
 end;
 THotKeys = array of TDescHotKey;

 TForm1 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   arrHotKeys: THotKeys;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin // инициализация массива
SetLength(arrHotKeys,Length(arrHotKeys)+1);
arrHotKeys[High(arrHotKeys)].FormComp:=0;
arrHotKeys[High(arrHotKeys)].Param:='1';
arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
arrHotKeys[High(arrHotKeys)].ShortCut:=118;
SetLength(arrHotKeys,Length(arrHotKeys)+1);
arrHotKeys[High(arrHotKeys)].FormComp:=0;
arrHotKeys[High(arrHotKeys)].Param:='5';
arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
arrHotKeys[High(arrHotKeys)].ShortCut:=119;
SetLength(arrHotKeys,Length(arrHotKeys)+1);
arrHotKeys[High(arrHotKeys)].FormComp:=0;
arrHotKeys[High(arrHotKeys)].Param:='17';
arrHotKeys[High(arrHotKeys)].Action:=hkaChoiceElList;
arrHotKeys[High(arrHotKeys)].ShortCut:=121;
end;

procedure TForm1.Button1Click(Sender: TObject);
var prArrHotKeys: THotKeys;
begin
prArrHotKeys:=Copy(arrHotKeys);
// удаляем первый элемент с индексом 0
Move(prArrHotKeys[0+1],prArrHotKeys[0],(Length(prArrHotKeys)-1-0)*SizeOf(TDescHotKey));
SetLength(prArrHotKeys,Length(prArrHotKeys)-1);
// удаляем элемент
SetLength(prArrHotKeys,Length(prArrHotKeys)+1);
prArrHotKeys[High(prArrHotKeys)].FormComp:=0;
prArrHotKeys[High(prArrHotKeys)].Param:='0';
prArrHotKeys[High(prArrHotKeys)].Action:=hkaChoiceElList;
prArrHotKeys[High(prArrHotKeys)].ShortCut:=116;
Label1.Caption:=prArrHotKeys[0].Param;
arrHotKeys:=Copy(prArrHotKeys);
Label1.Caption:=arrHotKeys[0].Param;
end;

Уже при третьем нажатии кнопки Button1, на входе обработчика Button1Click массив arrHotKeys имеет неправильную структуру элементов, что в конечном счете приводит к Invalid Point Operation.


vint45   (2005-01-25 14:44:00) [15]

я попробую сделать код покомпактнее и выложить его с указанием того, где возникает ошибка.


Arm79   (2005-01-25 14:43:00) [16]

будет работать правильно


KSergey   (2005-01-25 14:39:00) [17]

Вполне все работает, в том числе и с приведенной конструкцией
Явная ошибка в программе, только гда-то не в приведенном куске.


begin...end   (2005-01-25 14:30:00) [18]

> vint45   (25.01.05 14:29)

Ошибки - ? Код - ?


Наверх

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