Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.28;
Скачать: CL | DM;

Вниз

Access Violation при возврате из функции   Найти похожие ветки 

 
Tihinen   (2005-08-06 01:06) [0]

Не могу понять что не так. Имеется вот такой кусок программы.

type
 TDrawClass = class
 private
   fTarget:TCanvas;
   function SubDrawRoutine(a:integer;b,c,d:Integer;e:integer;f:integer):integer;

 public
   constructor Create(Target:TCanvas);
   destructor Destroy; override;
   function  Draw(DM:TMyMatrix;const DrawCycle:Integer=-1;Var1:Integer =0):Boolean;

// в качестве Target используется Саnvas созданного однажды Bitmap - чтото вроде теневого экрана
constructor TDrawClass.Create(Target:TCanvas);
begin
fTarget:=Target;
end;

destructor TDrawClass.Destroy;
begin
inherited Destroy;
end;

function TDrawClass.SubDrawRoutine(a:integer;b,c,d:Integer;e:integer;f:integer):integer;
begin
//вычисляются Rect1,Rect2,Rect3 исходя из параметров a,b,c,d,e,f
// исходя из них же грузится SourceBmp
//...

fTarget.CopyRect(Rect1,SourceBmp.Canvas,Rect1);
fTarget.CopyRect(Rect2,SourceBmp.Canvas,Rect2);
fTarget.CopyRect(Rect3,SourceBmp.Canvas,Rect3);
end;

function TDrawClass.Draw(DM:TMyMatrix;const DrawCycle:Integer=-1;Var1:Integer =0):Boolean;
begin
try
//
..
//циклически вызывается TDrawClass.SubDrawRoutine
//
Result:=True;
fTarget.Draw(0,0,ResX.GetBitmap("Top"));
fTarget.Draw(0,450,ResX.GetBitmap("Bottom"));
except
MessageBox(0,"1","1",0);
end;
end;

//на основной форме вызывается по таймеру Draw;
//...
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
begin
//...
try
MyDrawClass.Draw(DM,DrawCycle);
except
MessageBox(0,"2","2",0);
end;
//...
end;

происходит срабатывание второго эксепшна и вызывается второй мессаджбокс,
то есть Access Violation возникает на возврате из функции Draw, а не внутри нее.
Сопственно изза чего это может происходить? Причем возникает он совсем с непонятной периодичностью, то возникает то нет.
Но всегда одинаковый "по адресу 00000013 чтение адреса FFFFFFFF"
параметр DM: TMyMatrix = array [1..3,1..5] of integer является свойством третьего класса.
Мне вот кажется что дело тут вовсе не в рисовании, а в том что возврат из функции Draw осуществляется както коряво.
Памажите.


 
DrPass ©   (2005-08-06 01:32) [1]


> то есть Access Violation возникает на возврате из функции
> Draw,

Точно ли на возврате? А может, перед вызовом? Корректно ли инициализирован MyDrawClass? Или еще что?


 
Tihinen   (2005-08-06 01:53) [2]

Точно на возврате.
я вот ввел глобальную переменную DebugStr:String;
и функция Draw выглядит примерно так...
function TDrawClass.Draw;
begin
try
//
..
DebugStr:="1";
//..
DebugStr:="2";
//..
Result:=True;
DebugStr:="12";
fTarget.Draw(0,0,ResX.GetBitmap("Top"));
DebugStr:="13";
fTarget.Draw(0,450,ResX.GetBitmap("Bottom"));
DebugStr:="DrawExit";
except
MessageBox(0,"1","1",0);
end;
end;

и перед вызовом Draw - тоже самое
DebugStr:="0";
Draw;
DebugStr:="AfterExit";

и когда происходит экспшн - DebugStr всегда DrawExit, то есть последняя строчка функции Draw всегда выполняется. Такая вот штука :-/


 
Mx ©   (2005-08-06 02:14) [3]

А я вот подумал: с учетом того, что raise внутри except-блока в TDrawClass.Draw нет, то второе исключение может возникнуть лишь если внутри этого блока какая-то ошибка. Или, действительно, ошибка на самом возврате, но я себе это слабо представляю.

А нельзя ли привести весь код TDrawClass.Draw? Какого вида переменные в нем используются?


 
Джо ©   (2005-08-06 02:17) [4]


>  Или, действительно, ошибка на самом возврате, но я себе
> это слабо представляю.

Представить не сложно ;) Это может быть, например, из-за того, что внутри процедуры запорчен стэк.


 
Mx ©   (2005-08-06 02:20) [5]


> Джо ©   (06.08.05 02:17) [4]

"Сложно" для приведенного варианта, потому и запросил "весь код".

P.S. Блин, опять два часа ночи, а я всё не сплю. А ведь каждый день обещаю себе лечь вовремя и выспаться...


 
Tihinen   (2005-08-06 02:28) [6]

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

все именно вот так :

function Draw;
begin
try
 //...
 DebugStr:="DrawExit";
except
MessageBox(0,"1","1",0);
end;
end;

в теле программы
//....
try
DebugStr:="BeforeDraw";
Draw();
DebugStr:="AfterDraw";
except
MessageBox(0,"2","2",0);
end;
//....

На момент появления эксепшна DebugStr="DrawExit" !!!
Ну и если это чтото даст то вот эта функция. У меня были сомнения именно в передаче параметров в нее. Я бы предложил что это какой то системный сбой вообще не связанный с этим, поскольку используется DirectX и еще и Flash, но меня смущает, что происходит он всегда с функцией именно этой.

function  TAniDrum.Draw(DM:TDrumMatrix;const Cycle:Integer; FlashCount:integer):Boolean;
var i:integer;
   Upp,Mid,Btm:Integer;
   Shift:Integer;
begin
Result:=False;
try
for i:=1 to 5 do
 begin
 if (Cycle>0) and (Cycle<RotateCycles[i]) then
   begin
   Upp:=-((Cycle mod 5)+1);
   Mid:=Upp;
   Btm:=Upp;
   Shift:=0;
   end
 else
   begin
   Upp:=DM[1,i];
   Mid:=DM[2,i];
   Btm:=DM[3,i];
   if Cycle=RotateCycles[i] then
       Shift:=10
   else
       Shift:=0;
   end;
 Lop:="6";
 FlashCount:=FlashCount-GenerateDrum(i-1,Upp,Mid,Btm,Shift,FlashCount);
 Lop:="7";
 end; //for i:=1 to 5 do
Result:=True;
fTarget.Draw(0,0,ResX.GetBitmap("Top"));
fTarget.Draw(0,450,ResX.GetBitmap("Bottom"));
if (Cycle>RotateCycles[5]+1) or (Cycle=0) then Result:=False;
Lop:="DrawExit";
except
MessageBox(0,"1","1",0)
end;
end;


 
Tihinen   (2005-08-06 02:32) [7]

А как вот можно испортить стек? Вот выделенная и неочищенная память эт я понимаю. Но выделения памяти нигде я сопсна внутри функции не делаю.


 
Джо ©   (2005-08-06 02:44) [8]

Может быть все что угодно. Что, например, делает GenerateDrum? Что за массив RotateCycles - где объявлен и инициализирован? Что за ResX с загадочным методом GetBitmap? Почему GetBitmap вызывается, а, возможно, выделенный ресурс нигде не освобождается?
Одни вопросы...


 
Джо ©   (2005-08-06 02:44) [9]

Пробуй локализовать.


 
Tihinen   (2005-08-06 02:54) [10]

GenerateDrum ну если опустить логику и математику на уровне целочисленных делений и прочая опять же содержит вот такие штуки

SourceBmp:=ResX.GetBitmap("Rotate");
fTarget.CopyRect(RectN,SourceBmp.Canvas,RectN);

дык вот нащщот ResX.GetBitmap;

есть вот такой класс

type
 TResourceX = class
 private
   RS:TResourceStream;
   BMPList:TList;
   NameList:TStringList;
 public
   constructor Create;
   destructor Destroy; override;
   procedure AddJpeg(const ResName: string);
   procedure AddGif(const ResName: string);
   procedure AddBmp(const ResName: string);
   function  GetBitmap(const ResName: string):TBitmap;
end;

и в нем два вот таких метода. Тобишь при запуске все ресурсы загружаюцца в память, а потом когда надо получаю указатели на BMP изображения из памяти.

function TResourceX.GetBitmap(const ResName: string):TBitmap;
begin
Result:=TBitmap(BMPList[Namelist.IndexOf(UpperCase(ResName))]);
end;

procedure TResourceX.AddJpeg(const ResName: string);
var TmpImage:TJpegImage;
   Bmp:TBitmap;
begin
RS := TResourceStream.Create(0, ResName, "IMAGE");
TmpImage:=TJpegImage.Create;
TmpImage.LoadFromStream(RS);
TmpImage.DIBNeeded;
Bmp:=TBitmap.Create;
Bmp.Assign(TmpImage);
BMPList.Add(Bmp);
TmpImage.Free;
RS.Free;
NameList.Add(UpperCase(ResName));
end;

Ну и RotateCycles вот.

const RotateCycles: array [1..5] of integer =(8,16,24,32,40);

:)

Мне хотелось бы услышать про испорченный стек. Меня вот данный вопрос интересует. Потомучто звучит очень правдоподобно, но как это может выглядеть я почемуто не представляю.


 
Tihinen   (2005-08-06 02:57) [11]

Джо. Пробуй локализовать.
Что локализовывать?


 
Джо ©   (2005-08-06 03:02) [12]


> Мне хотелось бы услышать про испорченный стек. Меня вот
> данный вопрос интересует

А что тут интересного. Ну, вот самый простой пример:

procedure Proc;
var
 I: Integer;
 Arr: array [0..2] of Integer;
begin
 for I := 0 to 3 do
 begin
   Arr[I] := 10;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Proc
end;

Нажмешь на кнопку и получишь AV. Потому что массив расположен в стэке, а ты вышел за пределы массива (for I := 0 to 3), таким образом запортив стэк. Соответственно, запортив то, что в нем лежало, возможно, и адрес возврата из процедуры.


 
Джо ©   (2005-08-06 03:05) [13]


>  [11] Tihinen   (06.08.05 02:57)
> Джо. Пробуй локализовать.
> Что локализовывать?

Локализовать проблему. То есть, найти минимальное количество кода, при котором нет проблем. Затем потихоньку начинай добавлять (раскомментировать) остальные строки, наблюдая, когда проблема появится. Возможно, поможет пошаговая отладка с заходом во все процедуры (F7) с включенной опцией компилятора Use debug DCU"s.


 
Джо ©   (2005-08-06 03:13) [14]


> [13] Джо ©   (06.08.05 03:05)

Коряво и неверно выразился.
Закомментируй все тело процедуры, при выходе из которой вылетает AV. Затем, начинай раскомментировать по одной строчку, каждый раз компилируя и запуская. Когда появится AV, будешь знать, из-за какой строчки. Ну, ты меня понял, надеюсь :)


 
Anatoly Podgoretsky ©   (2005-08-06 11:55) [15]

Tihinen   (06.08.05 02:28) [6]
function Draw;

Не обманывай, это просто не откомпилируется и ни о каком AV говорить и не приходится.


 
Tihinen   (2005-08-08 21:23) [16]

К чему бы мне обманывать?

и с какой это радости не откомпилируецца то?

type TDrawClass = class



Страницы: 1 вся ветка

Текущий архив: 2005.08.28;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.027 c
14-1122965493
Игорь Шевченко
2005-08-02 10:51
2005.08.28
Наши программисты победили в Йокогаме


1-1123469073
TerminalHead
2005-08-08 06:44
2005.08.28
Защита программы паролем


14-1123156968
Knight
2005-08-04 16:02
2005.08.28
Подскажите алгоритм по которому можно отрисовать...


3-1121345286
Greg123
2005-07-14 16:48
2005.08.28
Создание индексов в TDBF


3-1121678289
Viktor1
2005-07-18 13:18
2005.08.28
Exception сервера об отсутствии прав у пользователя.