![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
![]() Здравствуйте!
Никак не могу понять почему вываливается ошибка доступа к памяти. Пользователь динамически создаёт список запрещённых частот, при удалении уже созданной из списка появляется ошибка. Частоты хранятся в динамическом массиве freq_array. Помогите пожалуйста! Код:
unit Unit2; interface uses Unit1, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm2 = class(TForm) Timer1: TTimer; GroupBox1: TGroupBox; GroupBox2: TGroupBox; Label1: TLabel; Edit1: TEdit; Label3: TLabel; GroupBox3: TGroupBox; Button3: TButton; Button1: TButton; Button4: TButton; procedure Edit1KeyPress(Sender: TObject; var Key: Char); procedure Timer1Timer(Sender: TObject); procedure ShowList; procedure ListButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; lab_empty: TLabel; implementation {$R *.dfm} procedure TForm2.ListButtonClick(Sender: TObject); var l_array, Index : integer; begin Index:= StrToInt(TComponent(Sender).Name[Length(TComponent(Sender).Name)])-1; l_array:= Length(freq_array); {$HINTS OFF} Finalize(freq_array[Index]); {$HINTS ON} if (l_array = 1) then begin SetLength(freq_array, 0); end else begin freq_array[Index]:= freq_array[l_array-1]; SetLength(freq_array, l_array-1); end; ShowList; end; procedure TForm2.Edit1KeyPress(Sender: TObject; var Key: Char); var a: Extended; i, k: Integer; freq_povtor: Boolean; s, h: String; begin if not (Key in ['0'..'9', #8, #13, '.', ',']) then Key:=#0 else if (Key = '.') then Key:=',' else if (Key = #13) then begin h:= Edit1.Text; if (Length(h)>10) then begin Label1.Font.Size:=12; Label1.Font.Color:=clRed; Label1.Top:= 36; Label1.Height:= 24; Label1.Caption:= 'Некорректное значение!'; Edit1.Clear; Timer1.Enabled:=True; end else begin s:= ''; for i:=1 To Length(h) Do begin if (h[i]='.') then s:=s+',' else s:=s+h[i]; end; if TryStrToFloat(s,a) then begin if (a<149) Or (a>150) And (a<173) Or (a>174) then begin Label1.Font.Size:=12; Label1.Font.Color:=clRed; Label1.Top:= 36; Label1.Height:= 24; Label1.Caption:= 'Неправильный диапазон!'; Edit1.Clear; Timer1.Enabled:=True; end else begin freq_povtor:=False; for k:=0 to length(freq_array)-1 do begin if (freq_array[k] = a) then freq_povtor:=True; end; if (freq_povtor=True) then begin Label1.Font.Size:=12; Label1.Font.Color:=clRed; Label1.Top:= 36; Label1.Height:= 24; Label1.Caption:= 'Частота уже есть в списке!'; Edit1.Clear; Timer1.Enabled:=True; end else begin Label1.Font.Size:=12; Label1.Font.Color:=clGreen; Label1.Top:= 36; Label1.Height:= 24; Label1.Caption:= 'Ввод успешен!'; SetLength(freq_array,length(freq_array)+1); freq_array[length(freq_array)-1]:= a; ShowList; Edit1.Clear; Timer1.Enabled:=True; end end end else begin Label1.Font.Size:=12; Label1.Font.Color:=clRed; Label1.Top:= 36; Label1.Height:= 24; Label1.Caption:= 'Некорректное значение!'; Edit1.Clear; Timer1.Enabled:=True; end; end; end; end; procedure TForm2.Timer1Timer(Sender: TObject); begin Timer1.Enabled:=False; Label1.Font.Size:=10; Label1.Font.Color:=clBlack; Label1.Top:= 29; Label1.Height:= 36; Label1.Caption:= 'Введите частоту в МГц в диапазоне 149...150 МГц или 173...174 МГц и нажмите клавишу "Enter"'; end; procedure TForm2.ShowList; var m, t: integer; lab_empty, lab_freq, lab_ce, lab_msg: TLabel; edit_freq: TEdit; but_freq: TButton; begin //Form1.Label3.Caption:= IntToStr(Length(list_array)); for t:= Form2.ComponentCount-1 downto 0 do begin if (Form2.Components[t].GetParentComponent=GroupBox1) then Form2.Components[t].Free; end; if (Length(freq_array)=0) then begin lab_empty:= TLabel.Create(Form2); lab_empty.Parent:= Form2.GroupBox1; lab_empty.Top:= 72; lab_empty.Left:= 216; lab_empty.Width:= 85; lab_empty.Height:= 19; lab_empty.Font.Color:= clMaroon; lab_empty.Font.Size:= 12; lab_empty.Font.Name:= 'Calibri'; lab_empty.Caption:= 'Список пуст'; Form2.GroupBox1.Height:= 110; end else begin Form2.GroupBox1.Height:= 110 + 35*(length(freq_array)-1); for m:=0 to length(freq_array)-1 do begin lab_freq:= TLabel.Create(Form2); lab_freq.Parent:= Form2.GroupBox1; lab_freq.Top:= 73+m*35; lab_freq.Left:= 17; lab_freq.Width:= 36; lab_freq.Alignment:= taRightJustify; lab_freq.Font.Color:= clBlack; lab_freq.Caption:= 'f'+IntToStr(m+1)+' ='; lab_freq.Name:='el_list1_'+ IntToStr(m+1); edit_freq:= TEdit.Create(Form2); edit_freq.Parent:= Form2.GroupBox1; edit_freq.Top:= 70+m*35; edit_freq.Left:= 59; edit_freq.Width:= 83; edit_freq.Font.Color:= clBlack; edit_freq.MaxLength:= 10; edit_freq.Text:= FloatToStr(freq_array[m]); edit_freq.Name:='el_list2_'+ IntToStr(m+1); lab_ce:= TLabel.Create(Form2); lab_ce.Parent:= Form2.GroupBox1; lab_ce.Top:= 73+m*35; lab_ce.Left:= 144; lab_ce.Font.Color:= clBlack; lab_ce.Caption:= 'МГц'; lab_ce.Name:='el_list3_'+ IntToStr(m+1); but_freq:= TButton.Create(Form2); but_freq.Parent:= Form2.GroupBox1; but_freq.Top:= 70+m*35; but_freq.Left:= 190; but_freq.Width:= 135; but_freq.Font.Color:= clBlack; but_freq.Font.Size:= 8; but_freq.Font.Name:= 'MS Sans Serif'; but_freq.Font.Style:= [fsBold]; but_freq.Caption:= 'Удалить из списка'; but_freq.Name:='el_list4_'+ IntToStr(m+1); but_freq.onClick:=ListButtonClick; lab_msg:= TLabel.Create(Form2); lab_msg.Parent:= Form2.GroupBox1; lab_msg.Top:= 75+m*35; lab_msg.Left:= 340; lab_msg.Alignment:= taLeftJustify; lab_msg.Font.Color:= clBlack; lab_msg.Font.Size:= 10; lab_msg.Font.Name:= 'Calibri'; lab_msg.Name:='el_list5_'+ IntToStr(m+1); lab_msg.Caption:=IntToStr(m); end; end; end; procedure TForm2.FormCreate(Sender: TObject); begin ShowList; end; end. |
#2
|
||||
|
||||
![]() Очень тяжелый код. Упростить можно много чего, но речь не об этом.
1. С какой целью Вы используете Finalize(freq_array[Index])? Вы же не динамическую структуру уничтожаете, да и для этого есть Dispose(). 2. Полагаю Вы не правильно понимаете действие процедуры Finalize. Она не удалит элемент массива. Вам нужно сдвинуть все элементы массива с индеском больше Index, на место удаляемого элемента (с индексом Index). Move(freq_array[Index+1], freq_array[Index], Length(freq_array) - Index + 1); Мог ошибиться в длине сдвигаемого участка массива, проверьте сами. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#3
|
|||
|
|||
![]() Цитата:
![]() С Finalize я экспериментировал (что с ней, что без - всё равно ошибка). С массивом у меня так: на место удаляемого элемента вставляется последний, а потом уменьшается длина массива на 1. Проблема возникает, когда нажимается динамически созданная кнопка с надписью "Удалить из списка", появляющаяся в списке вместе с добавленной частотой. Причём, если добавить две частоты и удалять вторую, происходит удаление частоты и кнопки из списка без ошибки (как надо). При этом, после каждого добавления или удаления частоты происходит перерисовка списка через процедуру ListShow. А вот если удалять первую частоту, третью и т.д. - всё грустно. ![]() Последний раз редактировалось Bosa, 30.04.2018 в 14:03. |
#4
|
||||
|
||||
![]() Мне лень перепечатывать код. Если не затруднит - выложите проект. Быстрее будет отладить, чем искать ошибку в браузере.
Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#5
|
|||
|
|||
![]() dr. F.I.N.
Ок, архив проекта во вложении |
#6
|
|||
|
|||
![]() Да, а не проще просто взять TListBox и в него напихать частоты, а кнопки сделать общими. Кстати, сами частоты можно прямо там в итемах хранить (через .Objects[]). Если число целое, то и вообще можно просто так туда засунуть через приведение типа. И интерфейс будет более стандартный, как у большинства программ...
|