![]() |
| ||
|
|
Новости |
Поиск |
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 и как с ним бороться?
pavel_guzhanov (2010-04-26 20:17:00) [61]А можно ли перед удалением компонента из массива также сделать, чтобы за компонентом не осталось никаких процедур? Если можно, то как?
Пробую сделать так:
TImage(pan[y,x]).OnClick:=nil;
pan[y,x].Free;
pan[y,x]:=nil;
но на первой строке опять получаю AV
jack128_ (2010-04-25 23:52:00) [62]Павел, ты б к Юрий © [11] прислушал бы.
Дмитрий Белькевич (2010-04-25 00:24:00) [63]
> После завершающего end'а сразу вылетает AV.
Если валится на end'ах, обычно это признак порушенного стёка. Например, неверным вызовом сторонних функций из длл.
Anatoly Podgoretsky (2010-04-24 18:47:00) [64]> pavel_guzhanov (24.04.2010 17:06:28) [28]
Ну и зачем тогда туда лезешь?
sniknik (2010-04-24 17:23:00) [65]> Подозрительны пара мест.
нашел еще ...
procedure TMainForm. OnClickImage(sender:TObject);
странное название... похоже получено не "стандартно" кликом на имидж, "обозвано" специально... зачем? возможно делана одна отдельная процедура, чтобы присваивать обработчикам многих динамически созданных иммеджей (массиву, которым рулит эта самая процедура (???)).
если так, и если это те самые которые после внутри процедуры удаляются... то стоит ли удивляться AV?
pavel_guzhanov (2010-04-24 17:10:00) [66]это процедура
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;
pavel_guzhanov (2010-04-24 17:06:00) [67]Включил дебаг DCU. Падает вот в этом куске файла System на выделенной строке:
@@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
Что сие обозначает, я не знаю :о(
jack128_ (2010-04-20 10:30:00) [68]
> что то я в хелпе от 2007ой дельфи не могу найти эту фразу.
> Значит в этой версии - можно Destroy юзать??
а, нашел. Тогда ладно.
jack128_ (2010-04-20 10:29:00) [69]
> F1: Do not call Destroy directly. Use the Free method.
что то я в хелпе от 2007ой дельфи не могу найти эту фразу. Значит в этой версии - можно Destroy юзать??
Германн (2010-04-20 00:58:00) [70]
> Какой такой стек, когда есть прекрасный сервис по удаленной
> отладке программ http://delphimaster.ru/cgi-bin/forum.pl
Уж очень тормозной этот сервис!
DVM (2010-04-20 00:43:00) [71]
> Игорь Шевченко © (18.04.10 21:53) [15]
> Delphi в момент исключения показывает стек вызовов, если
> кнопку Break нажать...
Какой такой стек, когда есть прекрасный сервис по удаленной отладке программ http://delphimaster.ru/cgi-bin/forum.pl
Loginov Dmitry (2010-04-20 00:28:00) [72]
> а чем Destroy не устраивает?
F1: Do not call Destroy directly. Use the Free method.
_Юрий (2010-04-19 21:19:00) [73]Стек вызовов посмотреть было бы не лишним.
Что еще можно сделать - собрать с включенной галкой "Use Debug DCU's"
Вероятно, информации о случившемся будет больше
pavel_guzhanov (2010-04-19 20:17:00) [74]убрал try - finally - end. Все равно после SL.Destroy (на этой строке ставлю брекпоинт) по F7 перехожу на end, а после него AV.
Изменение SL.Destroy на SL.Free ничего не изменило.
_Юрий (2010-04-19 19:10:00) [75]
> а чем Destroy не устраивает? Или FreeAndNil ?
FreeAndNil для данного случая вызывает две лишниеоперации (присвоение nil переменной, которая больше не используется, проверка на nil переменной, которая не может быть nil'ом в данном случае в принципе),
а Free - всего одну лишнюю операцию (проверка на nil того, что nil'ом быть не может)
Так что Free тут лучше, чем FreeAndNil
jack128_ (2010-04-19 16:18:00) [76]
> Чем Free не устраивает?
а чем Destroy не устраивает? Или FreeAndNil ?
Anatoly Podgoretsky (2010-04-19 00:26:00) [77]> Loginov Dmitry (19.04.2010 00:22:17) [17]
Тем что работает без ошибок, а у Destroy есть такая возможность.
Loginov Dmitry (2010-04-19 00:22:00) [78]
> При пошаговой отладке, после секции finally по клавише F7
> попадаю на end; который закрывает процедуру. А после него
> вылетает AV. Подскажите пожалуйста, откуда AV и как с ним
> бороться?
>
Правильно делает, что попадает в finally, а ошибку выдает уже в самом конце.
В данном примере нужно просто выяснить на какой именно строке происходит AV.
Можно каждую строчку завернуть в TRY..EXCEPT и логгировать ошибки. Где-то должна вылезти.
> Подозрительны пара мест.
>
> P := Bitmap.ScanLine[i];
> PR:=BitMapR.ScanLine[i];
Хорошо, если Height у обоих одинаковый.
У меня больше подозрение вызывает такое место:
if not CompareMem(P, PR, BitMap.Width) then
(но если пиксели действительно кодируются 1-м байтом, то шут с ними)
> finally
> SL.Destroy;
> end;
Чем Freeне устраивает?
Демо (2010-04-18 21:55:00) [79]Подозрительны пара мест.
P := Bitmap.ScanLine[i];
PR:=BitMapR.ScanLine[i];
Здесь нет утечки памяти?
и
pan[y,x].Free;
pan[y,x]:=nil;
А pan[y,x] больше нигде не используется?
Нет ли назначенной процедуры-обработчика на эти pan[x,y] ?
Игорь Шевченко (2010-04-18 21:53:00) [80]Delphi в момент исключения показывает стек вызовов, если кнопку Break нажать...