![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Процедура вызывает AV [D7, XP]
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.