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

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

Процедура вызывает AV [D7, XP]


Страницы:   1 2 3 4 5

pavel_guzhanov ©   (2010-04-18 19:36:00) 

Вот такой вот код процедуры:

procedure TMainForm.OnClickImage(sender:TObject);
var Name:String[10];
   i, j, k, l,m,c, a, x, y, xa, ya:SmallInt;
   BitMap, BitMapR : Graphics.TBitMap;
   P, PR : PByteArray;
   Image1, Image2: TImage;
   SL:TStringList;        
   S:String;
begin
 SL:=TStringList.Create;
 Name:=TControl(Sender as TImage).Name;
 y:=StrToInt(copy(name, 2, 2));
 x:=StrToInt(copy(name, 4, 2));
 m:=0;
 c:=0;
 try
   if Pan[y, x]<>nil then
     SL.Add(String(Pan[y, x].Name))
   else
     SL.Add('');
   while m<=c do
   begin
     y:=StrToInt(copy(name, 2, 2));
     x:=StrToInt(copy(name, 4, 2));
     for k:=1 to 4 do
     begin
       case k of
       1:begin
           xa:=x+1;
           ya:=y;
         end;
       2:begin
           xa:=x;
           ya:=y+1;
         end;
       3:begin
           xa:=x-1;
           ya:=y;
         end;
       4:begin
           xa:=x;
           ya:=y-1;
         end;
       end; //case
       if (xa<1) or (ya<1) or (xa>18) or (ya>12) or (Pan[yA,xA]=nil) then
         continue;
       Image1:=Pan[y, x];
       Image2:=Pan[ya, xa];
       BitMap:=Image1.Picture.Bitmap;
       BitMapR:=Image2.Picture.Bitmap;
       for i:=0 to Bitmap.Height - 1 do
       begin
         P := Bitmap.ScanLine[i];
         PR:=BitMapR.ScanLine[i];
         if not CompareMem(p, pr, BitMap.Width) then
         begin
           j:=i;
           Break;
         end;//if not
         j:=i;
       end;//for i
       if j=Bitmap.Height - 1 then  
       begin
         a:=0;

         for l:=0 to SL.Count-1 do
         begin
           if String(Pan[ya, xa].Name)=SL.Strings[l] then
           begin
             a:=l;
             break;
           end; //if string
           a:=l;
         end;// for l

       if a=SL.Count-1 then  
         SL.Add(String(Pan[ya, xa].Name));
       c:=SL.Count;
       end; //if j
       if (SL.Count>1) and (m<c) then
       begin
         name:=SL.Strings[m];
       end;// if sl.count and
       S:='';
       for l:=0 to SL.Count-1 do
       begin
         S:=S+SL.Strings[l];
       end; //for l
     end; //for k
     inc(m);
   end; //while
   for l:=0 to SL.Count-1 do
   begin
     if sl.Count>1 then
     begin
       y:=StrToInt(copy(SL.Strings[l], 2, 2));
       x:=StrToInt(copy(SL.Strings[l], 4, 2));
       pan[y,x].Free;
       pan[y,x]:=nil;
     end;// if sl.count
   end; //for l
   for i := 0 to 11 do
   begin
     for j:=0 to 17 do
     begin
       if pan[i+1, j+1]<>nil then
         pan[i+1,j+1].Parent:=Panel1;
     end; //for j
   end; //for i
 finally
   SL.Destroy;
 end;
end;


Все отрабатывает правильно. Но... При пошаговой отладке, после секции finally по клавише F7 попадаю на end; который закрывает процедуру. А после него вылетает AV. Подскажите пожалуйста, откуда AV и как с ним бороться?


Плохиш   (2010-04-29 10:20:00) [1]


> 12 ©   (28.04.10 16:44) [91]
>
> грустно смотреть

Просто весеннее обострение ;-)


sniknik   (2010-04-29 10:03:00) [2]

> Буду думать, как сделать по-другому :о)
чего тут думать? еще в [35] было указание на то как борлад подобное "обходит", посмотреть код в генофонде (несколько строк всего), да модифицировать "под себя".

а в [42] прямой пример замены ничего не меняющей ни в отображении и в логике, только проверки станут другими, не на nil а на видитмость.


pavel_guzhanov   (2010-04-29 08:49:00) [3]

Всем спасибо. По крайней мере я понял причину, по которой получается AV.

Буду думать, как сделать по-другому :о)


12   (2010-04-28 16:44:00) [4]

грустно смотреть


Игорь Шевченко   (2010-04-28 16:36:00) [5]

sniknik ©   (28.04.10 15:49) [89]

не плюйся, вылетит, не поймаешь


sniknik   (2010-04-28 15:49:00) [6]

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


oxffff   (2010-04-28 15:01:00) [7]

Читаю с середины второй день подряд.
И не могу понять в чем суть обсуждения?

Если во вложенном методе будет разрушен объект и это не приведет к проблемам, то ничего плохого нет.

А плохое это не только использование разрушенногого объекта, но и использование частично деинициализированного объекта.
Но ведь Tobject.Free по факту ссылается на выходе на разрушенный объект и работает же.
Это вопрос логики.


Игорь Шевченко   (2010-04-28 13:03:00) [8]


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


в чем разница ?


sniknik   (2010-04-28 12:55:00) [9]

> переведи.
по русски написано.

> Это обычный обработчик сообщения, тот же самый динамический метод, как и в WM_MOUSEUP
а ты не путай, при сабжевом глюке событие не вызывается вызывается метод.

> Вызов Free это не баг, но может привести к багу.
ВСЕ может привести к багу.


Игорь Шевченко   (2010-04-28 10:33:00) [10]

sniknik ©   (28.04.10 01:20) [83]


> он же по событию вызовется в общей очереди между обработчиками,
>  после отработавших и до возможных


переведи. Это обычный обработчик сообщения, тот же самый динамический метод, как и в WM_MOUSEUP


> вызов Free это не баг, и не приводит к багу


Вызов Free это не баг, но может привести к багу.


> лучше считай откуда можно... меньше получится.


Я начну считать, тебе мало не покажется


Германн   (2010-04-28 02:00:00) [11]


> лучше считай откуда можно... меньше получится.

+1
Опередил.

> И обсуждалось подобное не раз, чудес не было, только "свезло/не
> свезло".

(c) LVT


sniknik   (2010-04-28 01:20:00) [12]

> Free в release тоже вызывается из обработчика сообщения. Сообщения CM_RELEASE
ну и что? он же по событию вызовется в общей очереди междуобработчиками, после отработавших и до возможных... после "убийства" формы отправленных в "никуда" (событие на не существующий хендл к AV не приводят, только к невыполнению события).

вызов Free это не баг, и не приводит к багу, если только он не сделан в неправильном месте (до обращений к обьекту).

> из OnClick почему нельзя убивать
лучше считай откуда можно... меньше получится.


Игорь Шевченко   (2010-04-28 01:09:00) [13]


> только одно отношение, это аналог, когда "убивают" себя
> из своего же обработчика


Free в release тоже вызывается из обработчика сообщения. Сообщения CM_RELEASE

procedure TCustomForm.Release;
begin
 PostMessage(Handle, CM_RELEASE, 0, 0);
end;

procedure TCustomForm.CMRelease;
begin
 Free;
end;


из OnClick почему нельзя убивать - выяснили, Click срабатывает на MouseDown, а кроме него еще есть MouseUp к тому же контролу, уже в очереди.


sniknik   (2010-04-28 01:01:00) [14]

> только одно отношение
+ все компоненты формы "помрут" вместе с ней, т.что и из обработчика компонент лежащих на форме делать Free форме противопоказано.


sniknik   (2010-04-28 00:57:00) [15]

> Какое отношение Release имеет к обработчикам событий компонент, я честно не понимаю.
только одно отношение, это аналог, когда "убивают" себя из своего же обработчика. с формой такая ситуация происходит чаще, вот и позаботились.
и также это путь к обходу сабжа, ничего не мешает сделать тоже самое для имеджа например.


Игорь Шевченко   (2010-04-28 00:49:00) [16]

sniknik ©   (28.04.10 00:22) [77]


> типа отработал и все, и никуда не лезет, никого не вызывает,
>  и ни к чему не обращается (не в данный момент так в перспективе).
>


На перспективу лчуше вообще ничего не писать. Надежнее будет.


Игорь Шевченко   (2010-04-28 00:48:00) [17]

sniknik ©   (28.04.10 00:22) [77]


> для форм, с их обычным обилием, и в них же выполняющимися
> действиями, обработчиками Release вместо Free - узаконенная
> в доке догма.


Цитата из справки:

"Use Release to destroy the form and free its associated memory.
Any event handlers for the form or its children should use Release instead of Free.Failing to do so can cause a memory access error"

для уничтожения формы внутри ее самой и только для этого.

Какое отношение Release имеет к обработчикам событий компонент, я честно не понимаю.


sniknik   (2010-04-28 00:22:00) [18]

> Для потенциально любого обрабтчика - отнюдь не догма.
для форм, с их обычным обилием, и в них же выполняющимися действиями, обработчиками Release вместо Free - узаконенная в доке догма.

а вообще, для потенциального большинства, т.к. мало найдется событий ничего не наследующих (и не выполняющих потому неизвестно что, не в данный момент так в перспективе), и вообще независимых, без последствий, типа отработал и все, и никуда не лезет, никого не вызывает, и ни к чему не обращается (не в данный момент так в перспективе).


Игорь Шевченко   (2010-04-28 00:09:00) [19]

Соответственно, при


> procedure TForm1.ButtonClick(Sender: TObject);
> begin
>   //Sender.Free;
> end;
>
> procedure TForm1.ButtonMouseUpFree(Sender: TObject; Button:
>  TMouseButton;
>   Shift: TShiftState; X, Y: Integer);
> begin
>   Sender.Free;
> end;
>
> procedure TForm1.FormCreate(Sender: TObject);
> begin
>   FButton := TButton.Create(Panel1);
>   FButton.Parent := Panel1;
>   FButton.Top := 20;
>   FButton.Left := 20;
>   FButton.Caption := 'Click me';
>   FButton.OnClick := ButtonClick;
>   FButton.OnMouseUp := ButtonMouseUpFree;
> end;


Даже использование FastMM не вызывает ошибки


Игорь Шевченко   (2010-04-28 00:00:00) [20]

sniknik ©   (27.04.10 23:52) [74]

Для обработчика OnClick - да, догма, потому что он срабатывает на нажатие мыши. За что тебе спасибо :)

Для потенциально любого обрабтчика - отнюдь не догма.


Страницы:   1 2 3 4 5

Наверх

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