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 и как с ним бороться?


sniknik   (2010-04-27 23:52:00) [21]

догма...


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

Помогло воспроизвести ошибку только включение в проект FastMM с указанием Full Debug mode, при котором при освобождении объекта заведомо портится занимаемая им память.

Так что код действительно "как повезет" и не рекомендуется к использованию.


sniknik   (2010-04-27 23:18:00) [23]

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


sniknik   (2010-04-27 23:15:00) [24]

> Будет над чем поразмышлять :)
procedure       GetDynaMethod;
{       function        GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer;       }
asm
       { ->    EAX     vmt of class            }
       {       SI      dynamic method index    }
       { <-    ESI pointer to routine  }
       {       ZF = 0 if found         }
       {       trashes: EAX, ECX               }

       PUSH    EDI
       XCHG    EAX,ESI
       JMP     @@haveVMT
@@outerLoop:
       MOV     ESI,[ESI]
@@haveVMT:
       MOV     EDI,[ESI].vmtDynamicTable
       TEST    EDI,EDI
       JE      @parent
       MOVZX   ECX,word ptr [EDI]
       PUSH    ECX
       ADD     EDI,2
        REPNE   SCASW//ошибка здесь. на событии "обратного отщелкивания"  мыши после клика
       JE      @@found
       POP     ECX
@parent:
       MOV     ESI,[ESI].vmtParent
       TEST    ESI,ESI
       JNE     @@outerLoop
       JMP     @@exit

@@found:
       POP     EAX
       ADD     EAX,EAX
       SUB     EAX,ECX         { this will always clear the Z-flag ! }
       MOV     ESI,[EDI+EAX*2-4]

@@exit:
       POP     EDI
end;


Leonid Troyanovsky   (2010-04-27 22:38:00) [25]


> Игорь Шевченко ©   (27.04.10 22:25) [69]

> "Borland® Delphi® for Microsoft® Windows™ Version 10.0.2558.
> 35231 Update 2 Copyright © 2005 Borland® Software Corporation.

Здесь похвастать не чем, бо, не следил, не участвовал,
не ..  привлекался :)

> На двух версиях, которыми располагаю, проверил. Результат
> опубликовал :)

Результат любопытный и заслуживает, IMHO, текущего обсуждения.
Будет над чем поразмышлять :)

--
Regards, LVT.


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

Leonid Troyanovsky ©   (27.04.10 22:04) [68]


> Будет/не будет - код, один хрен, коряв.


нужда в корявом коде может быть одна - проверить факт, а не верить на слово.

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

"Borland® Delphi® for Microsoft® Windows™ Version 10.0.2558.35231 Update 2 Copyright © 2005 Borland® Software Corporation. All Rights Reserved."


> С необходимыми и достаточными условиями?
> And все версии?


На двух версиях, которыми располагаю, проверил. Результат опубликовал :)


Leonid Troyanovsky   (2010-04-27 22:04:00) [27]


> Игорь Шевченко ©   (27.04.10 21:41) [66]

> Могу конечно и ошибаться, но факт - вещь упрямая.

Завтра испытаю на Turbo Delphi 2006, доложусь.
Хотя, это и не снимает ответственности с других.

Будет/не будет - код, один хрен, коряв.
И что ж за нужда в оном? :)

--
Regards, LVT.


Leonid Troyanovsky   (2010-04-27 21:53:00) [28]


> Игорь Шевченко ©   (27.04.10 20:24) [63]

С необходимыми и достаточными условиями?
And все версии?

А накуа ж это сомнительное удовольствие?

--
Regards, LVT.


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

Leonid Troyanovsky ©   (27.04.10 21:34) [65]

Есть у меня стойкое ощущение, что часть догм перестала ими быть.

Нес па ?

Могу конечно и ошибаться, но факт - вещь упрямая.


Leonid Troyanovsky   (2010-04-27 21:34:00) [30]


> Игорь Шевченко ©   (27.04.10 20:24) [63]

> работает. Turbo Delphi 2006

Свезло.

--
Regards, LVT.


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

sniknik ©   (27.04.10 19:31) [61]


> сам ищи там где светлее, а я, если буду, только там где
> "потерял"...  


А у меня нету AV, мне нечего искать. Понял ?


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

Leonid Troyanovsky ©   (27.04.10 18:53) [60]


> В любом случае, в любой, IMHO, версии достаточно добавить
> после Sender.Free;
> ShowMessage(''); // это ж никак не обращение к полям фантома?
>
> и AV неизбежен.


Подвело тебя твое ИМНО

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


работает. Turbo Delphi 2006


> Ну не должен нормальный код содержать подобные кунштюки.
>
> Ведь знаешь ;)


Марксизм не догма, а руководство к действию.
Ведь знаешь ? :)

Я вот в упор не вижу причины, по которой в обработчике события надо обращатся после выполнения собственно обработчика к полям/методам инициатора события.

Сам метод обработчика живет в неудаляемом классе, так что аналогия с Release здесь никаким боком не подходит. И кстати, Release, как ни странно, тоже вызывает Free в обработчике события. Правда, события от сообщения.


Leonid Troyanovsky   (2010-04-27 19:39:00) [33]


> sniknik ©   (27.04.10 19:31) [61]

> "потерял"...  - реализация Free/ Release у форм. хоть весь

По-взрослому, Releasе - тоже костыль.
Но, подзащитный лишь пару раз с ним согрешил :)

--
Regards, LVT.


sniknik   (2010-04-27 19:31:00) [34]

> в посте [49] я показал. Чего-то недостаточно ?
сам ищи там где светлее, а я, если буду, только там где "потерял"...  - реализация Free/ Release у форм. хоть весь оставшийся генофонд сюда скопипасть.


Leonid Troyanovsky   (2010-04-27 18:53:00) [35]


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

---------------------------
Debugger Exception Notification
---------------------------
Project Project2.exe raised exception class EAccessViolation with message 'Access violation at address 0040367D in module 'Project2.exe'. Read of address 00000018'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help  
---------------------------
XP SP3 & D6
Лень искать в чьем оно модуле, бо подход крив по определению.
И обсуждалось подобное не раз, чудес не было, только "свезло/не свезло".

В любом случае, в любой, IMHO, версии достаточно добавить после Sender.Free;
ShowMessage(''); // это ж никак не обращение к полям фантома?
и AV неизбежен.

Ну не должен нормальный код содержать подобные кунштюки.
Ведь знаешь ;)

--
Regards, LVT.


12   (2010-04-27 14:21:00) [36]


> Игорь Шевченко ©   (27.04.10 10:58) [55]

D7 XP
AV
ставлю галку CPU, нажимаю ОК, yажимаю F7

TWinControl.MainWndProc
call FreeDeviceContexts


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

sniknik ©   (27.04.10 12:10) [57]


> раз у тебя не происходит AV от Free в своих обработчиках,
>  покажи его реализацию


в посте [49] я показал. Чего-то недостаточно ?

{RASkov} ©   (27.04.10 11:18) [56]

Ну и ? Место-то где ? Или ты полагаешь, что во всех версиях Delphi модули располгаются по одинаковым адресам ? Я тебя разочарую - это не так.


sniknik   (2010-04-27 12:10:00) [38]

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

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

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


{RASkov}   (2010-04-27 11:18:00) [39]

> [55] Игорь Шевченко ©   (27.04.10 10:58)

[D7] [WinXP Pro]
Результат:
---------------------------
Debugger Exception Notification
---------------------------
Project KillComponentfromEventHandler.exe raised exception class EAccessViolation with message 'Access violation at address 004032B8 in module 'KillComponentfromEventHandler.exe'. Read of address 0014D000'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help  
---------------------------


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

На Delphi 2010 под Win7 64 мой код тоже не вызывает AV. Других версий Delphi у меня нету. Если у кого будет желание, протрассируйте код на младших версиях и выложите результат.

Проект прост

program KillComponentfromEventHandler;

uses
 Forms,
 main in 'main.pas' {Form1};

{$R *.res}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.


object Form1: TForm1
 Left = 0
 Top = 0
 Caption = 'Form1'
 ClientHeight = 293
 ClientWidth = 426
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = 'Tahoma'
 Font.Style = []
 OldCreateOrder = False
 OnCreate = FormCreate
 PixelsPerInch = 96
 TextHeight = 13
 object Panel1: TPanel
   Left = 60
   Top = 40
   Width = 301
   Height = 185
   Caption = 'Panel1'
   TabOrder = 0
 end
end


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.


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

Наверх

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