Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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; // &#237;&#229; &#241;&#238;&#226;&#239;&#224;&#228;&#224;&#254;&#242;
         end;//if not
         j:=i;
       end;//for i
       if j=Bitmap.Height - 1 then  // &#241;&#238;&#226;&#239;&#224;&#228;&#224;&#254;&#242;
       begin
         a:=0;
// &#207;&#240;&#238;&#226;&#229;&#240;&#234;&#224; , &#229;&#241;&#242;&#252; &#235;&#232; &#226; &#241;&#242;&#240;&#232;&#237;&#227;&#235;&#232;&#241;&#242;&#229; &#243;&#230;&#229; &#242;&#224;&#234;&#224;&#255; &#231;&#224;&#239;&#232;&#241;&#252;
         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
// &#197;&#241;&#235;&#232; &#231;&#224;&#239;&#232;&#241;&#232; &#237;&#229;&#242;, &#242;&#238; &#228;&#238;&#225;&#224;&#226;&#235;&#255;&#229;&#236; &#237;&#238;&#226;&#243;&#254; &#231;&#224;&#239;&#232;&#241;&#252; &#226; &#241;&#242;&#240;&#232;&#237;&#227;&#235;&#232;&#241;&#242;
       if a=SL.Count-1 then  // &#229;&#241;&#235;&#232;  &#224; &#240;&#224;&#226;&#237;&#224; &#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#243; &#231;&#224;&#239;&#232;&#241;&#229;&#233; &#226; &#241;&#242;&#240;&#232;&#237;&#227;&#235;&#232;&#241;&#242;&#229;
                             //&#231;&#237;&#224;&#247;&#232;&#242; &#242;&#224;&#234;&#238;&#227;&#238; &#232;&#236;&#229;&#237;&#232; &#226; &#241;&#242;&#240;&#232;&#237;&#227;&#235;&#232;&#241;&#242;&#229; &#237;&#229;&#242;
         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
15-1264355410
GDI+
2010-01-24 20:50
2010.08.27
Нифига себе прогнозы!..


15-1268385262
Jeer
2010-03-12 12:14
2010.08.27
Нас посчитали


2-1273148921
ИванВ
2010-05-06 16:28
2010.08.27
ScrollBar


6-1217598621
Shamansky_ne
2008-08-01 17:50
2010.08.27
Soap как поменять пакет перед посылкой


15-1264404182
Polkin
2010-01-25 10:23
2010.08.27
ЗАГС - вопросы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский