Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
ВнизПроцедура вызывает AV Найти похожие ветки
← →
pavel_guzhanov © (2010-04-18 19:36) [0]Вот такой вот код процедуры:
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 и как с ним бороться?
← →
YurikGL © (2010-04-18 19:47) [1]может после end-а еще что то выполняется?
← →
Anatoly Podgoretsky © (2010-04-18 19:53) [2]> pavel_guzhanov (18.04.2010 19:36:00) [0]
Включи контроль диапазонов, а заодно и переполнения. Потом отпишись.
← →
Anatoly Podgoretsky © (2010-04-18 19:54) [3]> YurikGL (18.04.2010 19:47:01) [1]
Можешь не сомневаться, исполняется множество обработчиков.
← →
pavel_guzhanov © (2010-04-18 20:03) [4]
> Включи контроль диапазонов, а заодно и переполнения
Я конечно извиняюсь за глупый вопрос, но как их включить?
← →
YurikGL © (2010-04-18 20:23) [5]
> контроль диапазонов, а заодно и переполнения
идешь в самое начало кода, нажимаешь ctrl+o+o и потом читаешь тут
http://www.delphisources.ru/pages/faq/base/compiler_directives.html
или тут http://www.delphibasics.ru/1Compiler-directives.php
← →
Anatoly Podgoretsky © (2010-04-18 20:30) [6]> pavel_guzhanov (18.04.2010 20:03:04) [4]
Взгляни настройки проекта.
← →
pavel_guzhanov © (2010-04-18 20:47) [7]Включил. Легче не стало. Получаю следующую информацию:
Project ***.exe raised exception class EAccessViolation with message "Access violation at address 00403375 in module "***.exe". Read of address 00000028". Process stopped. Use Step or Run to continue.
После нажатия OK приложение не падает, а продолжает работать. При повторном выполнении процедуры такая же ошибка, только адреса отличаются.
← →
YurikGL © (2010-04-18 20:53) [8]
> pavel_guzhanov © (18.04.10 20:47) [7]
Судя по ошибке - обращение к несуществующему (несозданному) объекту....
← →
pavel_guzhanov © (2010-04-18 21:08) [9]а как определить, к какому объекту обращается? После завершающего end"а сразу вылетает AV.
← →
YurikGL © (2010-04-18 21:18) [10]
> pan[y,x].Free;
Оно потом нигде не используется? В какой-нибудь перерисовке...
← →
_Юрий © (2010-04-18 21:19) [11]Можно подключить FastMem в качестве менеджера памяти, и включить в его настройках подробный вывод информации.
← →
pavel_guzhanov © (2010-04-18 21:35) [12]
> Оно потом нигде не используется?
Используется. Но с проверкой на nil:
> 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
Больше нигде не используется.
← →
Anatoly Podgoretsky © (2010-04-18 21:45) [13]> pavel_guzhanov (18.04.2010 20:47:07) [7]
Не создан объект, ищи какой, можно попытаться найти строку с адресом 00403375
← →
Anatoly Podgoretsky © (2010-04-18 21:50) [14]
> Больше нигде не используется.
Верится с трудом, это же глобальная переменная или поле класса. Об объявление которой, ты скромно молчишь.
← →
Игорь Шевченко © (2010-04-18 21:53) [15]Delphi в момент исключения показывает стек вызовов, если кнопку Break нажать...
← →
Демо © (2010-04-18 21:55) [16]Подозрительны пара мест.
P := Bitmap.ScanLine[i];
PR:=BitMapR.ScanLine[i];
Здесь нет утечки памяти?
иpan[y,x].Free;
pan[y,x]:=nil;
А pan[y,x] больше нигде не используется?
Нет ли назначенной процедуры-обработчика на эти pan[x,y] ?
← →
Loginov Dmitry © (2010-04-19 00:22) [17]
> При пошаговой отладке, после секции 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 не устраивает?
← →
Anatoly Podgoretsky © (2010-04-19 00:26) [18]> Loginov Dmitry (19.04.2010 00:22:17) [17]
Тем что работает без ошибок, а у Destroy есть такая возможность.
← →
jack128_ (2010-04-19 16:18) [19]
> Чем Free не устраивает?
а чем Destroy не устраивает? Или FreeAndNil ?
← →
_Юрий © (2010-04-19 19:10) [20]
> а чем Destroy не устраивает? Или FreeAndNil ?
FreeAndNil для данного случая вызывает две лишние операции (присвоение nil переменной, которая больше не используется, проверка на nil переменной, которая не может быть nil"ом в данном случае в принципе),
а Free - всего одну лишнюю операцию (проверка на nil того, что nil"ом быть не может)
Так что Free тут лучше, чем FreeAndNil
← →
pavel_guzhanov © (2010-04-19 20:17) [21]убрал try - finally - end. Все равно после SL.Destroy (на этой строке ставлю брекпоинт) по F7 перехожу на end, а после него AV.
Изменение SL.Destroy на SL.Free ничего не изменило.
← →
_Юрий © (2010-04-19 21:19) [22]Стек вызовов посмотреть было бы не лишним.
Что еще можно сделать - собрать с включенной галкой "Use Debug DCU"s"
Вероятно, информации о случившемся будет больше
← →
Loginov Dmitry © (2010-04-20 00:28) [23]
> а чем Destroy не устраивает?
F1: Do not call Destroy directly. Use the Free method.
← →
DVM © (2010-04-20 00:43) [24]
> Игорь Шевченко © (18.04.10 21:53) [15]
> Delphi в момент исключения показывает стек вызовов, если
> кнопку Break нажать...
Какой такой стек, когда есть прекрасный сервис по удаленной отладке программ http://delphimaster.ru/cgi-bin/forum.pl
← →
Германн © (2010-04-20 00:58) [25]
> Какой такой стек, когда есть прекрасный сервис по удаленной
> отладке программ http://delphimaster.ru/cgi-bin/forum.pl
Уж очень тормозной этот сервис!
← →
jack128_ (2010-04-20 10:29) [26]
> F1: Do not call Destroy directly. Use the Free method.
что то я в хелпе от 2007ой дельфи не могу найти эту фразу. Значит в этой версии - можно Destroy юзать??
← →
jack128_ (2010-04-20 10:30) [27]
> что то я в хелпе от 2007ой дельфи не могу найти эту фразу.
> Значит в этой версии - можно Destroy юзать??
а, нашел. Тогда ладно.
← →
pavel_guzhanov © (2010-04-24 17:06) [28]Включил дебаг 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
Что сие обозначает, я не знаю :о(
← →
pavel_guzhanov © (2010-04-24 17:10) [29]это процедура
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;
← →
sniknik © (2010-04-24 17:23) [30]> Подозрительны пара мест.
нашел еще ...procedure TMainForm.OnClickImage(sender:TObject);
странное название... похоже получено не "стандартно" кликом на имидж, "обозвано" специально... зачем? возможно делана одна отдельная процедура, чтобы присваивать обработчикам многих динамически созданных иммеджей (массиву, которым рулит эта самая процедура (???)).
если так, и если это те самые которые после внутри процедуры удаляются... то стоит ли удивляться AV?
← →
Anatoly Podgoretsky © (2010-04-24 18:47) [31]> pavel_guzhanov (24.04.2010 17:06:28) [28]
Ну и зачем тогда туда лезешь?
← →
Дмитрий Белькевич (2010-04-25 00:24) [32]
> После завершающего end"а сразу вылетает AV.
Если валится на end"ах, обычно это признак порушенного стёка. Например, неверным вызовом сторонних функций из длл.
← →
jack128_ (2010-04-25 23:52) [33]Павел, ты б к Юрий © [11] прислушал бы.
← →
pavel_guzhanov © (2010-04-26 20:17) [34]А можно ли перед удалением компонента из массива также сделать, чтобы за компонентом не осталось никаких процедур? Если можно, то как?
Пробую сделать так:TImage(pan[y,x]).OnClick:=nil;
pan[y,x].Free;
pan[y,x]:=nil;
но на первой строке опять получаю AV
← →
sniknik © (2010-04-26 20:42) [35]посмотри на TForm.Release; в генофонде. как думаешь зачем так сделали?
← →
sniknik © (2010-04-26 20:46) [36]> чтобы за компонентом не осталось никаких процедур?
причем здесь "не осталось"? дело не в том чтобы не осталось, а в том чтобы не выполнялся код у "призрака", а код никуда не денется если ты его объект из него же и "грохаешь".
← →
Leonid Troyanovsky © (2010-04-26 21:26) [37]
> sniknik © (26.04.10 20:42) [35]
> посмотри на TForm.Release; в генофонде. как думаешь зачем
> так сделали?
[Антидидактическое] От отчаяния? :)
--
Regards, LVT.
← →
Игорь Шевченко © (2010-04-26 21:30) [38]Паша, у тебя ошибка в другом месте. Которое ты не привел. А зря.
← →
Leonid Troyanovsky © (2010-04-26 21:37) [39]
> Игорь Шевченко © (26.04.10 21:30) [38]
> А зря.
Каждый волен заблуждаться в меру своих заблуждений.
У нас свободная страна ;)
--
Regards, LVT.
← →
pavel_guzhanov © (2010-04-26 21:41) [40]
> у тебя ошибка в другом месте
Вот код 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))<2 then
x:="0"+intToStr(j+1)
else
x:=intToStr(j+1);
if length(intToStr(i+1))<2 then
y:="0"+intToStr(i+1)
else
y:=intToStr(i+1);
New.Name:="B"+ y+x;
new.Stretch:=true;
TImage(New).OnClick:=OnClickImage;
case Random(5) of
0:New.Picture.LoadFromFile("0.bmp");
1:New.Picture.LoadFromFile("1.bmp");
2:New.Picture.LoadFromFile("2.bmp");
3:New.Picture.LoadFromFile("3.bmp");
4:New.Picture.LoadFromFile("4.bmp");
5:New.Picture.LoadFromFile("5.bmp");
end;
New.Canvas.Brush.Style:=bsDiagCross;
pan[i+1,j+1]:=new;
pan[i+1,j+1].Parent:=Panel1;
end;
end;
except
ShowMessage(pan[i,j].Name);
end;
end;
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));
TImage(pan[y,x]).OnClick:=nil;
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.Free;
end;
end;
end.
Вот код Project1.dpr:program Project1;
uses
Forms,
MainFormUnit in "MainFormUnit.pas" {MainForm};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
Другого кода нет.
Страницы: 1 2 3 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.08 c