Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Ошибка при завершении программы


Автор: RemaGe 7.4.2010, 15:35
Доброго времени суток

Есть код

Код

var
  pan_ar: array of TsPanel;
  img_ar: array of TImage;

------------------------------------------------


  for i := 19 downto 0 do
  begin
      SetLength(pan_ar, length(pan_ar)+1);
      pan_ar[length(pan_ar)]:=TsPanel.Create(self);
      pan_ar[length(pan_ar)].Parent:= ScrollBox1;
      pan_ar[length(pan_ar)].Width:=100;
      pan_ar[length(pan_ar)].Height:=81;
      pan_ar[length(pan_ar)].Align:= alTop;
      pan_ar[length(pan_ar)].Caption:='sdfsdf';
      pan_ar[length(pan_ar)].Tag:=10;

      SetLength(img_ar, length(img_ar)+1);
      img_ar[length(img_ar)]:=TImage.Create(nil);
      img_ar[length(img_ar)].Parent:= pan_ar[length(pan_ar)];
      img_ar[length(img_ar)].Width:=48;
      img_ar[length(img_ar)].Height:=48;
      img_ar[length(img_ar)].Top:=18;
      img_ar[length(img_ar)].Left:=10;
      img_ar[length(pan_ar)].Tag:=10;
      img_ar[length(img_ar)].Picture.LoadFromFile('C:\Documents and Settings\Администратор\Мои документы\RAD Studio\Projects\Twi_meR\avatars\normal.JPG');
  end;


Тут создается 2 массива элементов, панели и картинки, картинки выводятся на панелях. Код работает нормально, но при завершении программы выскакивает пачка ошибок "Инструкция ххх обратилась по адресу yyyy", если убрать код создания Image, то все нормально, не могу понять почему с панелями все хорошо, а картинки тянут за собой ошибку.
Пробовал сделать так 

Код

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var i:integer;
begin
  for i:=Form1.ComponentCount-1 downto 0 do
  if Components[i].Tag=10 then Components[i].Free;

  SetLength(pan_ar, 0);
  SetLength(img_ar, 0);
end;

Все равно выскакивает ошибка.

Если верить точкам останова - ошибка происходит после выполнения FormClose, хотя и при пустом FormClose тоже происходит.

Что я делаю не так?

Автор: CodeMonkey 7.4.2010, 15:46
Потому что отсчёт в массивах с нуля.

Автор: Snowy 7.4.2010, 15:54
Цитата(RemaGe @  7.4.2010,  15:35 Найти цитируемый пост)
Тут создается 2 массива элементов
Не верю.

Цитата(RemaGe @  7.4.2010,  15:35 Найти цитируемый пост)
Пробовал сделать так 
Зачем?
Достаточно при создании в Create указать Owner'a, а не nil и тот сам позаботится об уничтожении детёныша.

Автор: RemaGe 7.4.2010, 15:55
CodeMonkey, 

Не догнал -) Что не так?

Добавлено через 4 минуты и 35 секунд
Snowy, 

Цитата

Не верю.


А где же табличка "Сарказм" ? -)

Цитата

указать Owner'a, а не nil 


Self пойдет? Попробовал nil заменить на Self и на Form1, все равно ругается -(

Автор: Snowy 7.4.2010, 16:02
Ну тут много неясностей.
Зачем создаются массивы?
Зачем в массивах заполняется только последний элемент?
Откуда цифра 19?
Зачем нужна переменная i?
Если планировалось инициировать все элементы массива под каждый контрол, то зачем перебирать контролы, если можно просто уничтожить все объекты массивов.
Ну и в конце концов, зачем вообще массивы, когда проще задействовать списки для старых версий или generic для новых версий delphi...
Приведённый код, хоть и компилируется, но принципиально бессмысленный.

Автор: RemaGe 7.4.2010, 16:10
Snowy, 
Там колличество элементов изначально неизвестно, выясняется по ходу программы, я просто лишний код с переменными убрал.

"зачем вообще массивы, когда проще задействовать списки для старых версий или generic для новых версий delphi"

Сел читать про дженерики -)


Автор: Snowy 7.4.2010, 16:21
В качестве Owner'a вполне подойдёт панель-папа
Из-за наличия повторяющихся конструкций, код плохо читаем.
При наличии неизвестного числа элементов, списки и выглядят и читаются куда лучше.
Под новый элемент лучше завести переменную, а не обращаться каждый раз к массиву.
Код

  img := TImage.Create(p);
  img.Parent := p;
  img.Width:=48;
  img.Height:=48;
  img.Top:=18;
  img.Left:=10;
  img.Tag:=10;
  img.Picture.LoadFromFile('C:\Documents and Settings\Администратор\Мои документы\RAD Studio\Projects\Twi_meR\avatars\normal.JPG');
  imglist.Add(img);
Выглядит гораздо лучше.
А ещё лучше
Код

  img := TImage.Create(p);
  with img do begin
    Parent := p;
    Width:=48;
    Height:=48;
    Top:=18;
    Left:=10;
    Tag:=10;
    Picture.LoadFromFile('C:\Documents and Settings\Администратор\Мои документы\RAD Studio\Projects\Twi_meR\avatars\normal.JPG');
  end;
  imglist.Add(img);
Хотя причины ошибки это не решает, но глазки напрягаются меньше и легче искать.
А причина скорее всего в автоуничтожении.
Либо в деструкторах, либо что-то где-то некорректно привязано.
Нужно либо найти что, либо уничтожить объекты по списку/массиву перед уничтожением формы.

Автор: RemaGe 7.4.2010, 18:25
Snowy, 
Спасибо за помощь -)
Сейчас с дженериками разберусь. потом буду с этим разбираться.

Автор: CodeMonkey 7.4.2010, 20:18
Цитата(RemaGe @  7.4.2010,  15:55 Найти цитируемый пост)
Не догнал -) Что не так?

SetLength(pan_ar, ...) говорит о том, что pan_ar - динамический массив. Динамические массивы отсчитывают элементы с нуля. Т.е. если длина массива Length(pan_ar), то в нём доступны элементы с 0 по Length(pan_ar) - 1 (или, что то же самое: с Low(pan_ar) по High(pan_ar)). 

Вы же заполняете элементы с 1 по Length(pan_ar) - со сдвигом в 1 элемент вправо, портя, таким образом, память. 

Замена pan_ar[length(pan_ar)] на pan_ar[length(pan_ar) - 1] или pan_ar[High(pan_ar)] должна была решить проблему.

Автор: RemaGe 8.4.2010, 17:32
CodeMonkey, 
Спасибо за помощь -)


Snowy, 
А вам за указание пути. Перевел на тлист - проблема исчезла, кода стало меньше, и он стал проще -)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)