Official Soldat Forums

Server Talk => Scripting Discussions and Help => Topic started by: Swompie on March 27, 2010, 01:28:57 pm

Title: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 27, 2010, 01:28:57 pm
Well, I've got a massive problem with Access Violations in my Zombie Survival script.
I've heard that they can be caused by (Global) Dynamic Arrays, is that true?

Thanks for help ;)
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Hacktank on March 27, 2010, 03:10:02 pm
I doubt it, i use dynamic arrays in droves and i dont get access violations. The best way to find the source of the access violations is to comment out large parts of the script. Or even better you can use 'try'

Code: [Select]
OnPlayerKill(Killer,Victim: byte; Weapon: string);
var line: int;
begin
try
// your normal script stuff here, for example
if killer <> victim then givexp(killler,322); line := line + 1;
inckills(killler,1); line := line + 1;
// ect
except
writeln('___________________________________________________________');
writeln('OnPlayerKill Error Captured on line: '+tostr(line));
writeconsole(ID,'Login error detected, attempting to recover important data',$ffff0000);
writeln('Error: ' + exceptiontostring(exceptiontype,exceptionparam));
writeln('killer='+tostr(killer)+'('+getplayerstat(killer,'name') + 'victim='+tostr(victim)+'('+getplayerstat(victim,'name'));
writeln('___________________________________________________________');
end;
end;

And when the error goes off it will give you the line and function of the error. Note: my example uses functions called givexp() and inckills(), if either of those had the problem in them then the error would still report as onplayerkill, you would have to add a 'try' block to them aswell if you determine that something in onplayerkill is the problem.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 27, 2010, 03:50:20 pm
Thanks, gonna try that, commenting out parts won't work since it would make the script not working right :(
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: DorkeyDear on March 27, 2010, 04:38:40 pm
I once had an issue with dynamic arrays (it was local to a function, not necessarily global) and it some reason didn't actually create the array automatically, and was yelling at me when I did anything to it. It may be necessary to do MyArray := []; before doing anything to it.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Gizd on March 27, 2010, 05:57:52 pm
Access violations evade try blocks somehow(just a tip).
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 29, 2010, 11:44:37 am
Ok, I added try-except blocks over the whole serverside procedures.

This error looks like it came up right after the try, before the try-except part I didn't change the Line variable to anything:
AppOnIdle - Line:  - Error: Out of Global Vars range

Some parts where it said there are errors:
Code: (pascal) [Select]
//OnPlayerCommand:
if lowercase(getpiece(Text, ' ', 0)) <> '/login' then begin
  Line := 2;
  WriteLn('CMD[' + IDToName(ID) + '] ' + text);
end;

//OnPlayerRespawn:
if GetPlayerStat(ID, 'team') <> ZombieTeam then begin
  Line := 6;
  Command('/setteam' + inttostr(ZombieTeam) + ' ' + inttostr(ID));
end;

//AppOnIdle:
if GetPlayerStat(i, 'human') = true then begin
  Line := 16;
    if Player[i].infected then begin
      Player[i].Infected        := false;
      Player[i].InfectOnRespawn := false;
      Player[i].ZombieClass     := 1;
      Command('/setteam' + inttostr(HumanTeam) + ' ' + inttostr(i));
    end;
  // Here begins Line 17


Anyone idea?  :|
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Gizd on March 29, 2010, 02:34:01 pm
Out of Globals Vars range <> Access Violation

I've read your post 3 times and I still don't get where is the error.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 29, 2010, 04:13:22 pm
You're not the only one /:
But I think I'll replace the Dynamic Arrays if I don't find any solution, then we'll see if they caused it.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Hacktank on March 30, 2010, 12:12:33 am
Can the Player array actually support every possible id index?Show us it's declaration.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 30, 2010, 02:26:33 am
Quote
var
   Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: dnmr on March 30, 2010, 03:40:10 am
Quote
var
   Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/
try starting it from 0. Just try...
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: ShadowDancer on March 30, 2010, 05:21:45 pm
I've noticed this error(out of globar variable) when i saved big arrays(500 records) to file(normal arrays, not dynamic). I think, that soldat have limited memory. Any better idea?
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Hacktank on March 30, 2010, 05:37:50 pm
From what i can gather you cannot do any checks with getarraylength/arrayhigh, or set it with setarraylength if you set the original size of the array with brackets. That may be your problem.

@Shadow:
Pretty sure the SSC array size limit is 255 (byte constraint).
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on March 31, 2010, 04:52:36 am
From what i can gather you cannot do any checks with getarraylength/arrayhigh, or set it with setarraylength if you set the original size of the array with brackets. That may be your problem.

But how should the Non-Dynamic Array cause these problems then?
Btw. I've got 4 Dynamic Arrays, aswell I don't use the 0th slot. Could that be the problem?
I set these now to some value and uploaded it yesterday, I'm gonna look later if it did crash again.



Ok, just looked up and it did, errors getting more weird, and now it really looks like the Dynamic Arrays are causing that shit.
Quote from: Errors
AppOnIdle - Line: 12 - Error: Out Of Range
AppOnIdle - Line: 9 - Error: Out of Proc Range
AppOnIdle - Line: 28 - Error: Exception: Type Mismatch
OnPlayerCommand - Line: 5 - Error: Out of Global Vars range - Text: buy 6

Quote from: AppOnIdle Errors:
Code: [Select]
Line := 12;
if (Bots[player[i].ZombieClass].Weap <> GetPlayerStat(i, 'primary')) and (GetPlayerStat(i, 'alive') = true) then begin
  Line := 13;
There could be only one way to cause Out of Range errors here, if Player.ZombieClass goes below zero, or, over 3. Which is never the case because I've made it so it can't do it.

Code: [Select]
if (player[i].draw) and (player[i].nodraw = 0) then
  drawtext(i, '$' + IntToStr(player[i].money) + iif((wave > 0) and (mapchangetimer = -1) and (survivetimer < 1000), BR + 'Survive ' + IntToStr(survivetimer) + ' seconds', ''), 150, cmoney, 0.11, 30, 370);
I've changed that DrawText() Part slightly in the next version, but I do not think that the and in the iif() could cause errors.

Code: [Select]
    Line := 28;
  if SurviveTimer = 60 then Msg(0, 'One more minute!', cGreen);
  if SurviveTimer = 10 then Msg(0, 'Ten seconds!', cGreen);
  if (SurviveTimer < 6) and (SurviveTimer > 0) then Msg(0, inttostr(SurviveTimer) + '..', cGreen);
end else begin
  Line := 29;
  :|
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Hacktank on March 31, 2010, 11:36:46 pm
Just a hunch, but are you doing something like this:
Code: [Select]
procedure foo();
var i: byte;
begin
for i := 1 to getarraylength(dynamicarray) do begin
   stuff;
   end;
end;

If so then that is the problem.
Code: [Select]
for i := 1 to getarraylength(dynamicarray)-1 do begin
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on April 01, 2010, 03:16:51 am
But how could that be the problem when I know, how large the Arrays are set?
I only set their length in ActivateServer(), when the data is loaded.

I set the variable which holds the array length, and use it for the loops. So I don't really need the GetArrayLength.
(Even though any stuff I use the Arrays in is displayed correctly)
Code: (pascal) [Select]
  LengthShopArray := strtoint(readini(ini, 'Shop Settings', 'LengthShopArray', '20'));
  SetArrayLength(Shop, LengthShopArray + 1);

Could it be a problem when I don't use the 0th slot?
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: ShadowDancer on April 01, 2010, 05:30:25 am
But look - dynamic arrays are counted from 0 like C/C++ so

Code: [Select]
SetArrayLength(Array, 15);
for i := 0 to 14 do Array[i] := smthing;

Are you sure, that in loops all is ok? Make smthing like Writeln(IntToStr(Counter)); to debug code.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on April 01, 2010, 07:29:47 am
The size is correct since I set it +1 so it goes from 0..20 (21) instead of 0..19 (20).
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: SpiltCoffee on April 01, 2010, 09:22:00 am
If you do happen to rewrite any data outside of the array's defined range (either through type declaration or SetArrayLength), what happens is you start to overwrite blocks of memory, and this is where your access violations can start to occur.

Pascal and Delpi do not complain when you access an index that happens to be outside of the defined range of your array type, so if you did this...

Code: [Select]
procedure Test();
var
  myArray: array [0..3] of integer;
begin
  myArray[123] := 0;
end;

... no errors should be produced in compilation, but there is a very very high chance that an access violation will occur because that happens to overwrite memory of your program. All the [0..3] does is defines the index offset and how many items to store in the array. Same deal goes for SetArrayLength (and remember that dynamic arrays ALWAYS start at 0, even if you copy into it an array that was starting at 17).

Just make sure your logic is not screwed up and you're accidentally incrementing one too many and accessing outside of the array length.

EDIT: I don't know how alike Soldat's ScriptCore and Pascal are, but since there is a chance there is, keep in mind that when assigning one dynamic array to another (even through parameters), the dynamic array variable being assigned to will be given a pointer, so it will always be referencing the exact same array in memory as the initial array you gave it was (e.g. it doesn't copy). Just thought that tip might help.
Title: Re: Dynamic Arrays - Origin of Access Violations?
Post by: Swompie on April 01, 2010, 11:19:54 am
Like I said in some posts above, I only set the length of the arrays once in ActivateServer.
Also the ranges of the arrays are correct, because anything work like it should.
Another annoying thing is, they do not occur at the same place, once they come up in AppOnIdle, then, in OnPlayerCommand.
One thing I thought by what it could be caused, was that I don't use the 0th index slot of the arrays.
But when I later declared even these slots with any value, the Access Violations still appeared.


Btw. I replaced the Dynamic Arrays with Non-Dynamics, seems to work fine now. It really looks like that they caused the Access Violations :|