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-27 10:36:00) [41]

sniknik ©   (27.04.10 01:32) [52]


> а я высказывал подозрения


Ты следователь ? Или у тебя Delphi тоже полевого, облегченного образца, без исходников ?

Раз у тебя происходит AV в моем примере, ну так покажи, в каком оно месте происходит. Проще ж некуда.


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


> Игорь Шевченко ©   (27.04.10 01:23) [51]
>
> sniknik ©   (27.04.10 01:20) [50]
>
>
> > проверь свой пример на D7.
>
>
> Подари - проверю.

Так зачем тогда на форме ввода вопроса на ДМ создана возможность указания версии Дельфи?
Игорь, это перебор, имхо.


sniknik   (2010-04-27 01:32:00) [43]

> Я привел код деструкторов
а я высказывал подозрения в различиях во Free

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

еще как вариант цикл выборки сообщений, возможно, каким то боком.

так зачем сравнивать деструкторы?

> где происходит AV ( и почему).
вот чего я точно не хочу делать, так это выяснять почему только для того чтобы что то доказать тебе, то что это не работает в D7. хочешь проверь, хочешь прими как данность, хочешь не верь. мне пофигу.


Игорь Шевченко   (2010-04-27 01:23:00) [44]

sniknik ©   (27.04.10 01:20) [50]


> проверь свой пример на D7.


Подари - проверю.

Я привел код деструкторов, сравни со своим, если есть отличия, давай посмотрим.
Кроме всего прочего, ты в D7 можешь узнать (и выложить в форум) именно то место, где происходит AV (и почему).


sniknik   (2010-04-27 01:20:00) [45]

> А что там уточнять ?
версию дельфи нужно уточнять, когда говоришь "а у меня так работает".

> Где что не так ?
Turbo Delphi 2006, Windows XP SP3
> Процедура вызывает AV [ D7, XP]

проверь свой пример на D7.


Игорь Шевченко   (2010-04-27 01:02:00) [46]

sniknik ©   (27.04.10 00:50) [47]

Turbo Delphi 2006, Windows XP SP3

А что там уточнять ?

procedure TForm1.ButtonClick(Sender: TObject);

mov eax,edx
call TObject.Free
ret

end;


destructor TWinControl.Destroy;
var
 I: Integer;
 Instance: TControl;
begin
 Destroying;
 if FDockSite then
 begin
   FDockSite := False;
   RegisterDockSite(Self, False);
 end;
 FDockManager := nil;
 FDockClients.Free;
 if Parent <> nil then RemoveFocus(True);
 if FHandle <> 0 then DestroyWindowHandle;
 I := ControlCount;
 while I <> 0 do
 begin
   Instance := Controls[I - 1];
   Remove(Instance);
   Instance.Destroy;
   I := ControlCount;
 end;
 FBrush.Free;
 if FObjectInstance <> nil then Classes.FreeObjectInstance(FObjectInstance);
 FPadding.Free;
 inherited Destroy;
end;


destructor TControl.Destroy;
begin
 Application.ControlDestroyed(Self);
 if (FHostDockSite <> nil) and not (csDestroying in FHostDockSite.ComponentState) then
 begin
   FHostDockSite.RemoveFreeNotification(Self);
   FHostDockSite.Perform(CM_UNDOCKCLIENT, 0, Integer(Self));
   SetParent(nil);
   Dock(NullDockSite, BoundsRect);
   FHostDockSite := nil;
 end else
   SetParent(nil);
 FActionLink.Free;
 FActionLink := nil;
 FConstraints.Free;
 FFont.Free;
 StrDispose(FText);
 FMargins.Free;
 inherited Destroy;
end;


destructor TComponent.Destroy;
begin
 Destroying;
 if FFreeNotifies <> nil then
 begin
   while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0) do
     TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);
   FreeAndNil(FFreeNotifies);
 end;
 DestroyComponents;
 if FOwner <> nil then FOwner.RemoveComponent(Self);
 inherited Destroy;
end;


Где что не так ?


sniknik   (2010-04-27 00:54:00) [47]

может в следующих версиях дельфи и сделали удаление через событие (реальное в основном цикле выборки, по типу Release у форм), но в D7 это не так.
версию нужно уточнять.


sniknik   (2010-04-27 00:50:00) [48]

Игорь Шевченко ©   (27.04.10 00:31) [44]
AV

D7, XP

> Стоит положить кнопку не на форму, а на панель, как этот метод перестанет работать.
в таком виде тоже не работает.


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

DVM ©   (27.04.10 00:36) [45]

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;

type
 TForm1 = class(TForm)
   Panel1: TPanel;
   procedure FormCreate(Sender: TObject);
 private
   FButton: TButton;
   procedure ButtonClick(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ButtonClick(Sender: TObject);
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;
end;

end.


DVM   (2010-04-27 00:36:00) [50]


> Игорь Шевченко ©   (27.04.10 00:31) [44]
>

Стоит положить кнопку не на форму, а на панель, как этот метод перестанет работать.


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


> AV исчезнет. нельзя так удалять, из обработчика свой объект.


unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
 private
   FButton: TButton;
   procedure ButtonClick(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ButtonClick(Sender: TObject);
begin
 Sender.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FButton := TButton.Create(Self);
 FButton.Parent := Self;
 FButton.Top := 20;
 FButton.Left := 20;
 FButton.Caption := 'Click me';
 FButton.OnClick := ButtonClick;
end;

end.


sniknik   (2010-04-26 23:28:00) [52]

> замени это ... на
или на
if Sender <> pan[y,x] then begin
 //TImage(pan[y,x]).OnClick:=nil;
 pan[y,x].Free;
 pan[y,x]:= nil;
end;

чтобы были удаления, но не было AV (сразу очевидно какое к нему приводит)


sniknik   (2010-04-26 23:13:00) [53]

pavel_guzhanov ©   (26.04.10 21:41) [40]
>> у тебя ошибка в другом месте
не верь, главная в том про что говорил.

вот, для пробы, замени это
TImage(pan[y,x]).OnClick:=nil;
pan[y,x].Free;
pan[y,x]:=nil;

на
pan[y,x].Visible:= false;

AV исчезнет. нельзя так удалять, из обработчика свой объект.


Игорь Шевченко   (2010-04-26 22:42:00) [54]

new:=TImage.Create(Panel1);
//Вот здесь надо Parent присвоить
    New.Height:=25;
    New.Width:=25;
    New.Top:=i*25;
    New.Left:=j*25;

а не здесь

  pan[i+1,j+1].Parent:=Panel1;


>    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


А это нафиг ?

>    if sl.Count>1 then
>      begin
>        y:=StrToInt(copy(SL.Strings[l], 2, 2));
>        x:=StrToInt(copy(SL.Strings[l], 4, 2));
>        TImage(pan[y,x]).OnClick:=nil;
>        pan[y,x].Free;
>        pan[y,x]:=nil;
>      end;// if sl.count


ты здесь с координатами не ошибаешься ? в смысле х с у не путаешь ?

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


pavel_guzhanov   (2010-04-26 21:41:00) [55]


> у тебя ошибка в другом месте

Вот код MainFormUnit.pas:
unit MainFormUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, Math;

type
 TMainForm = class(TForm)
   Panel1: TPanel;
   Button1: TButton;
   procedure OnClickImage(sender:TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   Pan:array [1..12, 1..18] of TImage;
 end;

var
 MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.Button1Click(Sender: TObject);
var New:TImage;
   i, j: Integer;
   x,y:String[2];
begin
 for i := 0 to 11 do
 begin
   for j:=0 to 17 do
   begin
     pan[i+1,j+1].Free;
     pan[i+1,j+1]:=nil;
   end; //for j
 end; //for i

 try
 Randomize;
 for I := 0 to 11 do
 begin
   for j:=0 to 17 do
   begin
     new:=TImage.Create(Panel1);
     New.Height:=25;
     New.Width:=25;
     New.Top:=i*25;
     New.Left:=j*25;
     if length(intToStr(j+1))


Leonid Troyanovsky   (2010-04-26 21:37:00) [56]


> Игорь Шевченко ©   (26.04.10 21:30) [38]

>  А зря.

Каждый волен заблуждаться в меру своих заблуждений.
У нас свободная страна ;)

--
Regards, LVT.


Игорь Шевченко   (2010-04-26 21:30:00) [57]

Паша, у тебя ошибка в другом месте. Которое ты не привел. А зря.


Leonid Troyanovsky   (2010-04-26 21:26:00) [58]


> sniknik ©   (26.04.10 20:42) [35]

> посмотри на TForm.Release; в генофонде. как думаешь зачем
> так сделали?

[Антидидактическое] От отчаяния? :)

--
Regards, LVT.


sniknik   (2010-04-26 20:46:00) [59]

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


sniknik   (2010-04-26 20:42:00) [60]

посмотри на TForm.Release; в генофонде. как думаешь зачем так сделали?


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

Наверх

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