Official Soldat Forums
Server Talk => Scripting Discussions and Help => Topic started 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 ;)
-
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'
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.
-
Thanks, gonna try that, commenting out parts won't work since it would make the script not working right :(
-
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.
-
Access violations evade try blocks somehow(just a tip).
-
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:
//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? :|
-
Out of Globals Vars range <> Access Violation
I've read your post 3 times and I still don't get where is the error.
-
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.
-
Can the Player array actually support every possible id index?Show us it's declaration.
-
var
Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/
-
var
Player: Array [1..32] of tPlayer;
I checked this twice if I did it that way ;/
try starting it from 0. Just try...
-
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?
-
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).
-
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.
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
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.
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.
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;
:|
-
Just a hunch, but are you doing something like this:
procedure foo();
var i: byte;
begin
for i := 1 to getarraylength(dynamicarray) do begin
stuff;
end;
end;
If so then that is the problem.
for i := 1 to getarraylength(dynamicarray)-1 do begin
-
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)
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?
-
But look - dynamic arrays are counted from 0 like C/C++ so
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.
-
The size is correct since I set it +1 so it goes from 0..20 (21) instead of 0..19 (20).
-
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...
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.
-
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 :|