Форум: "Основная";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.051 c