PDA

View Full Version : Still stumped with EAccess Violation Error (UnDelphiX)



Wizard
12-11-2007, 11:31 AM
Guys, I'm bugged with this error. It's driving me insane! Error EACCESS VIOLATION with message ACCESS VIOLATION at address 00479966 ... Delphi tells me the error ocurred in DXSprite Class, procedure TSprite.Dead and in the line:
FEngine.FDeadList.Add(Self);

I posted previously about the same error, I thought it had gone away but no. Problem is that it only happens in full screen mode and it sort of happens when it whants too. I tried setting breakpoints but can't find the error in my code. Someone said it might be that an item in dxSpriteEngine.Engine.items list is invalid or points to nill. How do I check for an invalid item?

Anyone experiencing the same problem or know what's causing it? Any help would be appreciated.

Wizard
14-11-2007, 09:46 AM
OK. I finally killed the EACCESS VIOLATION error...I hope so, did a lot of testing and it seems to be resolved :-)

The problem seems to be this:

- I had DXSpriteEngine.Items.Clear

- Which I changed to:

for i:= DXSpriteEngine.Engine.AllCount-1 downto 0 do
begin
if (DXSpriteEngine.Engine.Items[i] <> nil) then
begin
DXSpriteEngine.Engine.Items[i].dead;
end;
end;

- Which also caused the error and finally I changed it to

DXSpriteEngine.ENGINE.Clear, which seems to be doing the job of clearing/freeing my sprites.

seiferalmasy
15-11-2007, 02:54 PM
the engine clear isnt bug proof either. I used it and went to the example you gave which sorted me. Also, I figured out why I was having access errors:

Make sure your sprite is being killed before it is allowed to execute a domove event.

Let me explain

In my pong game, I kill all 3 sprites when a round is over then a new round begins they are recreated. If your sprite is killed and then domove is being run it is no longer available and will show an access error. It will usually happen if you have sprites being created right after being killed.

To fix make sure you call Spriteengine.dead; DIRECTLY AFTER killing sprites (force it to be used immediately following destroy of sprites). This will make sure dead is updated before the move section.

Also place Spriteengine.dead; ABOVE your Spriteengine.move; in your timer.

Wizard
16-11-2007, 08:10 AM
Hi, thanks for the reply. I don't know, I immediately got the same error when I went back to: for i:= DXSpriteEngine.Engine.AllCount-1 downto 0 do ...... Delphi stops at Sprite.Dead, FEngine.FDeadList.Add(Self);

And when I call spriteEngine.dead immediately after calling bullet.dead in my collission procedure I get an error about Index being out of bounds...

I did put .dead before .move as you suggested and changed back to engine.clear and no errors.

Do you maybe know when UnDelphiX will be made bug free? I know I should be learing other libraries like SDL and OpenGl, but I like UnDelphiX and it will allways have a soft spot for me because I started game programming with it :-)

User137
16-11-2007, 10:44 AM
Just making sure... Your collision function doesn't accidentally hold another count variable or refers to removed objects?

Wizard
17-11-2007, 08:57 AM
This is my collision procedure:


procedure TFormGame.BulletCollision&#40;Sender&#58;TObject;var done&#58;Boolean&#41;;
begin
if &#40;sender is TEnemy&#41; then
begin
Enemy &#58;= TEnemy&#40;sender&#41;;
if &#40;not Enemy.Hit&#41; then
begin
Explode &#58;= TExplode.Create&#40;dxSpriteEngine.Engine&#41;;
Explode.X &#58;= Enemy.X;
Explode.Y &#58;= Enemy.Y;
Enemy.hit &#58;= true;
Enemy.Dead;
Bullet.Dead;
Inc&#40;Points,100&#41;;
Inc&#40;EnemyCount,1&#41;;
if &#40;enemy.hit&#41;then
begin
FormGame.DXWaveList.Items.Find&#40;'Explode'&#41;.Play&#40;fal se&#41;;
Enemy &#58;= TEnemy.create&#40;dxspriteEngine.Engine&#41;;
end;
end;
end
else

Legolas
17-11-2007, 12:43 PM
procedure TFormGame.BulletCollision&#40;Sender&#58;TObject;var done&#58;Boolean&#41;;
begin
if &#40;sender is TEnemy&#41; then
begin
Enemy &#58;= TEnemy&#40;sender&#41;;
if &#40;not Enemy.Hit&#41; then
begin
Explode &#58;= TExplode.Create&#40;dxSpriteEngine.Engine&#41;;
Explode.X &#58;= Enemy.X;
Explode.Y &#58;= Enemy.Y;
Enemy.hit &#58;= true;
Enemy.Dead; <---------------
Bullet.Dead;
Inc&#40;Points,100&#41;;
Inc&#40;EnemyCount,1&#41;;
if &#40;enemy.hit&#41;then <-----------------
begin
FormGame.DXWaveList.Items.Find&#40;'Explode'&#41;.Play&#40;fal se&#41;;
Enemy &#58;= TEnemy.create&#40;dxspriteEngine.Engine&#41;;
end;

end;
end
else

You are calling enemy.hit after an enemy.dead call. Maybe this could cause some issues

seiferalmasy
18-11-2007, 02:55 AM
true!

Wizard
18-11-2007, 10:18 AM
Thanks for the replies guys.


procedure TFormGame.BulletCollision&#40;Sender&#58;TObject;var done&#58;Boolean&#41;;
begin
if &#40;sender is TEnemy&#41; then
begin
Enemy &#58;= TEnemy&#40;sender&#41;;
if &#40;not Enemy.Hit&#41; then
begin
Explode &#58;= TExplode.Create&#40;dxSpriteEngine.Engine&#41;;
Explode.X &#58;= Enemy.X;
Explode.Y &#58;= Enemy.Y;
Enemy.hit &#58;= true;
Enemy.Dead; <---------------
Bullet.Dead;
Inc&#40;Points,100&#41;;
Inc&#40;EnemyCount,1&#41;;
&#91;b&#93; if &#40;enemy.hit&#41;then <---------// Should it be if &#40;enemy.deaded&#41;?&#91;/b&#93; begin
FormGame.DXWaveList.Items.Find&#40;'Explode'&#41;.Play&#40;fal se&#41;;
Enemy &#58;= TEnemy.create&#40;dxspriteEngine.Engine&#41;;
end;

end;
end
else
Or should it be :


Enemy.Dead; <---------------
Bullet.Dead;
Inc&#40;Points,100&#41;;
Inc&#40;EnemyCount,1&#41;;
FormGame.DXWaveList.Items.Find&#40;'Explode'&#41;.Play&#40;fal se&#41;;
Enemy &#58;= TEnemy.create&#40;dxspriteEngine.Engine&#41;;

Legolas
18-11-2007, 12:02 PM
You will need to call Enemy.dead only when you are sure that you don't need to access the Enemy object anymore:


Enemy := TEnemy(sender);
if (not Enemy.Hit) then
begin
Enemy.hit := true;
Enemy.doSomething();
Enemy.whatever();
Enemy.foo := 12;
...

if (Enemy.hit) then
begin
DoSomeStuff();
...
end;

Enemy.Dead; // After this call, you can't access Enemy object anymore!
end;

Wizard
18-11-2007, 05:33 PM
Thanks for all the tips guys :wink:

I have now removed this code from the collision procedure and placed it in my psPlaying state. Enemy.dead is now the final call in the collision procedure and is not accessed thereafter. Seems to be working 100%.

if (enemy.hit) then
begin
Enemy := TEnemy.create(dxspriteEngine.Engine);
end;